brightway-basic-explorer 0.9.dev1__tar.gz → 0.9.dev3__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 (15) hide show
  1. {brightway_basic_explorer-0.9.dev1 → brightway_basic_explorer-0.9.dev3}/PKG-INFO +2 -1
  2. {brightway_basic_explorer-0.9.dev1 → brightway_basic_explorer-0.9.dev3}/brightway_basic_explorer/__init__.py +98 -20
  3. {brightway_basic_explorer-0.9.dev1 → brightway_basic_explorer-0.9.dev3}/brightway_basic_explorer.egg-info/PKG-INFO +2 -1
  4. {brightway_basic_explorer-0.9.dev1 → brightway_basic_explorer-0.9.dev3}/brightway_basic_explorer.egg-info/SOURCES.txt +1 -0
  5. brightway_basic_explorer-0.9.dev3/brightway_basic_explorer.egg-info/requires.txt +1 -0
  6. {brightway_basic_explorer-0.9.dev1 → brightway_basic_explorer-0.9.dev3}/pyproject.toml +2 -2
  7. {brightway_basic_explorer-0.9.dev1 → brightway_basic_explorer-0.9.dev3}/COPYING +0 -0
  8. {brightway_basic_explorer-0.9.dev1 → brightway_basic_explorer-0.9.dev3}/README.md +0 -0
  9. {brightway_basic_explorer-0.9.dev1 → brightway_basic_explorer-0.9.dev3}/brightway_basic_explorer/icons/emission.png +0 -0
  10. {brightway_basic_explorer-0.9.dev1 → brightway_basic_explorer-0.9.dev3}/brightway_basic_explorer/icons/natural_resource.png +0 -0
  11. {brightway_basic_explorer-0.9.dev1 → brightway_basic_explorer-0.9.dev3}/brightway_basic_explorer/icons/process.png +0 -0
  12. {brightway_basic_explorer-0.9.dev1 → brightway_basic_explorer-0.9.dev3}/brightway_basic_explorer/icons/unknown.png +0 -0
  13. {brightway_basic_explorer-0.9.dev1 → brightway_basic_explorer-0.9.dev3}/brightway_basic_explorer.egg-info/dependency_links.txt +0 -0
  14. {brightway_basic_explorer-0.9.dev1 → brightway_basic_explorer-0.9.dev3}/brightway_basic_explorer.egg-info/top_level.txt +0 -0
  15. {brightway_basic_explorer-0.9.dev1 → brightway_basic_explorer-0.9.dev3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: brightway-basic-explorer
3
- Version: 0.9.dev1
3
+ Version: 0.9.dev3
4
4
  Summary: Implement basic GUI to explorer brightway ativities
5
5
  Author-email: Benoît GSCHWIND <benoit.gschwind@minesparis.psl.eu>, OIE - Mines Paris PSL <benoit.gschwind@minesparis.psl.eu>
6
6
  Maintainer-email: Benoît GSCHWIND <benoit.gschwind@minesparis.psl.eu>
@@ -16,6 +16,7 @@ Classifier: Programming Language :: Python :: 3.13
16
16
  Requires-Python: >=3.10
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: COPYING
19
+ Requires-Dist: ipython
19
20
  Dynamic: license-file
20
21
 
21
22
  # Brightway Basic Explorer
@@ -4,7 +4,7 @@ from IPython.external.qt_for_kernel import QtGui, QtCore
4
4
  from IPython.lib.guisupport import start_event_loop_qt4, get_app_qt4, is_event_loop_running_qt4
5
5
 
6
6
  import os
7
- import matplotlib
7
+ import sys
8
8
  import bw2data
9
9
 
10
10
  def activity_to_json(act):
@@ -18,6 +18,40 @@ def activity_to_json(act):
18
18
  a["exchanges"] = exs
19
19
  return a
20
20
 
21
+ def activity_to_json_with_params(act, params):
22
+ try:
23
+ from lca_algebraic.params import (
24
+ all_params,
25
+ _complete_and_expand_params,
26
+ _getAmountOrFormula,
27
+ )
28
+
29
+ from sympy import Basic, Symbol
30
+ except:
31
+ raise Exception("lca_algebraic not found, please install it before using show_activity_with_params")
32
+
33
+ a = dict(act)
34
+ exs = list()
35
+ for e in act.exchanges():
36
+ de = dict(bw2data.get_activity(e["input"]))
37
+
38
+ amount = _getAmountOrFormula(e)
39
+
40
+ # Params provided ? Evaluate formulas
41
+ if isinstance(amount, Basic):
42
+ print(amount)
43
+ new_params = [(name, value) for name, value in _complete_and_expand_params(params, list(all_params().keys())).items()]
44
+ print(new_params)
45
+ amount = amount.subs(new_params).evalf()
46
+ print(amount)
47
+ de["computed_amount"] = True
48
+
49
+ de["amount"] = amount
50
+ de["formula"] = e.get("formula", None)
51
+ exs.append(de)
52
+ a["exchanges"] = exs
53
+ return a
54
+
21
55
  class QStandardItemRO(QtGui.QStandardItem):
22
56
  def __init__(self, *args, data=None, **kwargs):
23
57
  super().__init__(*args, **kwargs)
@@ -46,10 +80,13 @@ class TableModel(QtGui.QStandardItemModel):
46
80
  for k in ["name", "unit", "categories", "location", "amount", "formula"]
47
81
  ]
48
82
 
83
+ if "computed_amount" in e:
84
+ row[-2].setForeground(QtGui.QBrush(QtCore.Qt.GlobalColor.red))
85
+
49
86
  etype = e.get("type", "unknown")
50
87
  if etype == "emission":
51
88
  path = os.path.join(os.path.dirname(__file__), "icons", "emission.png")
52
- elif etype == "process":
89
+ elif etype in {"process", "processwithreferenceproduct"}:
53
90
  path = os.path.join(os.path.dirname(__file__), "icons", "process.png")
54
91
  elif etype == "natural resource":
55
92
  path = os.path.join(os.path.dirname(__file__), "icons", "natural_resource.png")
@@ -89,11 +126,9 @@ class ActionMenu(QtGui.QMenu):
89
126
  class ActivityWindow(QtGui.QMainWindow):
90
127
  keep = dict()
91
128
 
92
- def __init__(self, act):
129
+ def __init__(self, activity_json):
93
130
  super().__init__()
94
- self.act = act
95
-
96
- data = activity_to_json(act)
131
+ self.activity_key = (activity_json["database"], activity_json["code"])
97
132
 
98
133
  self.setWindowTitle("Activity Viewer")
99
134
  self.setGeometry(100, 100, 800, 600)
@@ -109,7 +144,7 @@ class ActivityWindow(QtGui.QMainWindow):
109
144
 
110
145
  for i, k in enumerate(["database", "name", "location", "unit", "categories", "type"]):
111
146
  grid.addWidget(QtGui.QLabel(f"{k}:"), i, 0)
112
- x = QtGui.QLabel(f"{str(data.get(k, '-'))}")
147
+ x = QtGui.QLabel(f"{str(activity_json.get(k, '-'))}")
113
148
  x.setTextInteractionFlags(QtCore.Qt.TextInteractionFlag.TextSelectableByMouse)
114
149
  grid.addWidget(x, i, 1)
115
150
  next_row = grid.rowCount()
@@ -134,13 +169,13 @@ class ActivityWindow(QtGui.QMainWindow):
134
169
  self.tree_view.setAlternatingRowColors(True)
135
170
 
136
171
  self.model = TableModel()
137
- self.model.load(data["exchanges"])
172
+ self.model.load(activity_json["exchanges"])
138
173
  self.tree_view.setModel(self.model)
139
174
  self.tree_view.doubleClicked.connect(self.doubleCliked)
140
175
  self.tree_view.setExpandsOnDoubleClick(False)
141
176
  self.tree_view.setSelectionBehavior(QtGui.QAbstractItemView.SelectionBehavior.SelectItems)
142
177
  #self.tree_view.rightClick.connect(self.rightClick)
143
- self.tree_view.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
178
+ self.tree_view.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu)
144
179
  self.tree_view.customContextMenuRequested.connect(self.context_menu)
145
180
 
146
181
  def context_menu(self, point):
@@ -149,8 +184,8 @@ class ActivityWindow(QtGui.QMainWindow):
149
184
  self.action_menu.exec(self.tree_view.viewport().mapToGlobal(point))
150
185
 
151
186
  def closeEvent(self, ev):
152
- if self.act.key in ActivityWindow.keep:
153
- del ActivityWindow.keep[self.act.key]
187
+ if self.activity_key in ActivityWindow.keep:
188
+ del ActivityWindow.keep[self.activity_key]
154
189
  super().closeEvent(ev)
155
190
 
156
191
  def update_filter(self, *args):
@@ -173,22 +208,57 @@ class ActivityWindow(QtGui.QMainWindow):
173
208
  def explore(self, index):
174
209
  r = index.row()
175
210
  v = self.model.root.child(r, 0).data()
176
- show_activity(bw2data.get_activity((v["database"], v["code"])))
211
+ show_activity(bw2data.get_activity((v["database"], v["code"])), self.params)
177
212
 
178
213
  def show(self, *args, **kwargs):
179
214
  super().show(*args, **kwargs)
180
215
  self.tree_view.setColumnWidth(0, 400)
181
216
 
182
- def show_activity(act):
183
- if 'module://matplotlib_inline.backend_inline' == matplotlib.backends.backend:
184
- print("WARNING: ActivityGUI will block, use `%matplotlib qt` to avoid blocking")
185
- if matplotlib.backends.backend != "qtagg":
186
- print(f"unexpected backend {matplotlib.backends.backend}")
217
+ class ActivityWindowWithParams(ActivityWindow):
218
+ keep = dict()
219
+
220
+ def __init__(self, activity_json, params):
221
+ super().__init__(activity_json)
222
+ self.params = params
223
+
224
+ def closeEvent(self, ev):
225
+ if self.activity_key in ActivityWindow.keep:
226
+ del ActivityWindowWithParams.keep[self.activity_key]
227
+ super().closeEvent(ev)
228
+
229
+ def explore(self, index):
230
+ r = index.row()
231
+ v = self.model.root.child(r, 0).data()
232
+ show_activity_with_params(bw2data.get_activity((v["database"], v["code"])), self.params)
233
+
234
+ # Replace IPython version to one compatible with Qt6
235
+ def start_event_loop_qt4(app=None):
236
+ """Start the qt event loop in a consistent manner."""
237
+ if app is None:
238
+ app = get_app_qt4([""])
239
+ if not is_event_loop_running_qt4(app):
240
+ app._in_event_loop = True
241
+ if hasattr(app, "exec_"):
242
+ app.exec_()
243
+ else:
244
+ app.exec()
245
+ app._in_event_loop = False
246
+ else:
247
+ app._in_event_loop = True
248
+
249
+ def _show_activity(cls, activity_json, *args):
250
+
251
+ if 'matplotlib' in sys.modules:
252
+ import matplotlib
253
+ if hasattr(matplotlib.backends, "backend"):
254
+ if 'qt' not in matplotlib.backends.backend:
255
+ print("WARNING: ActivityGUI will block, use `%matplotlib qt` to avoid blocking")
256
+
187
257
  app = get_app_qt4()
188
258
 
189
- if (window := ActivityWindow.keep.get(act.key, None)) is None:
190
- window = ActivityWindow(act)
191
- ActivityWindow.keep[act.key] = window
259
+ if (window := cls.keep.get((activity_json["database"], activity_json["code"]), None)) is None:
260
+ window = cls(activity_json, *args)
261
+ cls.keep[(activity_json["database"], activity_json["code"])] = window
192
262
  window.show()
193
263
 
194
264
  if not is_event_loop_running_qt4(app):
@@ -196,6 +266,14 @@ def show_activity(act):
196
266
 
197
267
  window.activateWindow()
198
268
 
269
+ def show_activity(act):
270
+ activity_json = activity_to_json(act)
271
+ _show_activity(ActivityWindow, activity_json)
272
+
273
+ def show_activity_with_params(act, params):
274
+ activity_json = activity_to_json_with_params(act, params)
275
+ _show_activity(ActivityWindowWithParams, activity_json, params)
276
+
199
277
  def close_all():
200
278
  for w in list(ActivityWindow.keep.values()):
201
279
  w.close()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: brightway-basic-explorer
3
- Version: 0.9.dev1
3
+ Version: 0.9.dev3
4
4
  Summary: Implement basic GUI to explorer brightway ativities
5
5
  Author-email: Benoît GSCHWIND <benoit.gschwind@minesparis.psl.eu>, OIE - Mines Paris PSL <benoit.gschwind@minesparis.psl.eu>
6
6
  Maintainer-email: Benoît GSCHWIND <benoit.gschwind@minesparis.psl.eu>
@@ -16,6 +16,7 @@ Classifier: Programming Language :: Python :: 3.13
16
16
  Requires-Python: >=3.10
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: COPYING
19
+ Requires-Dist: ipython
19
20
  Dynamic: license-file
20
21
 
21
22
  # Brightway Basic Explorer
@@ -5,6 +5,7 @@ brightway_basic_explorer/__init__.py
5
5
  brightway_basic_explorer.egg-info/PKG-INFO
6
6
  brightway_basic_explorer.egg-info/SOURCES.txt
7
7
  brightway_basic_explorer.egg-info/dependency_links.txt
8
+ brightway_basic_explorer.egg-info/requires.txt
8
9
  brightway_basic_explorer.egg-info/top_level.txt
9
10
  brightway_basic_explorer/icons/emission.png
10
11
  brightway_basic_explorer/icons/natural_resource.png
@@ -12,8 +12,8 @@ name = "brightway-basic-explorer"
12
12
  description = "Implement basic GUI to explorer brightway ativities"
13
13
  readme = "README.md"
14
14
  license-files = ["COPYING"]
15
- version = "0.9.dev1"
16
- dependencies = [ ]
15
+ version = "0.9.dev3"
16
+ dependencies = [ "ipython" ]
17
17
  requires-python = ">= 3.10"
18
18
  keywords = ["lca", "ecoinvent", "brightway"]
19
19
  classifiers = [