brightway-basic-explorer 0.9.dev2__tar.gz → 0.9.dev4__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.dev2 → brightway_basic_explorer-0.9.dev4}/PKG-INFO +1 -1
  2. {brightway_basic_explorer-0.9.dev2 → brightway_basic_explorer-0.9.dev4}/brightway_basic_explorer/__init__.py +124 -27
  3. {brightway_basic_explorer-0.9.dev2 → brightway_basic_explorer-0.9.dev4}/brightway_basic_explorer.egg-info/PKG-INFO +1 -1
  4. {brightway_basic_explorer-0.9.dev2 → brightway_basic_explorer-0.9.dev4}/pyproject.toml +1 -1
  5. {brightway_basic_explorer-0.9.dev2 → brightway_basic_explorer-0.9.dev4}/COPYING +0 -0
  6. {brightway_basic_explorer-0.9.dev2 → brightway_basic_explorer-0.9.dev4}/README.md +0 -0
  7. {brightway_basic_explorer-0.9.dev2 → brightway_basic_explorer-0.9.dev4}/brightway_basic_explorer/icons/emission.png +0 -0
  8. {brightway_basic_explorer-0.9.dev2 → brightway_basic_explorer-0.9.dev4}/brightway_basic_explorer/icons/natural_resource.png +0 -0
  9. {brightway_basic_explorer-0.9.dev2 → brightway_basic_explorer-0.9.dev4}/brightway_basic_explorer/icons/process.png +0 -0
  10. {brightway_basic_explorer-0.9.dev2 → brightway_basic_explorer-0.9.dev4}/brightway_basic_explorer/icons/unknown.png +0 -0
  11. {brightway_basic_explorer-0.9.dev2 → brightway_basic_explorer-0.9.dev4}/brightway_basic_explorer.egg-info/SOURCES.txt +0 -0
  12. {brightway_basic_explorer-0.9.dev2 → brightway_basic_explorer-0.9.dev4}/brightway_basic_explorer.egg-info/dependency_links.txt +0 -0
  13. {brightway_basic_explorer-0.9.dev2 → brightway_basic_explorer-0.9.dev4}/brightway_basic_explorer.egg-info/requires.txt +0 -0
  14. {brightway_basic_explorer-0.9.dev2 → brightway_basic_explorer-0.9.dev4}/brightway_basic_explorer.egg-info/top_level.txt +0 -0
  15. {brightway_basic_explorer-0.9.dev2 → brightway_basic_explorer-0.9.dev4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: brightway-basic-explorer
3
- Version: 0.9.dev2
3
+ Version: 0.9.dev4
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>
@@ -1,7 +1,7 @@
1
1
  # coding=utf-8
2
2
 
3
3
  from IPython.external.qt_for_kernel import QtGui, QtCore
4
- from IPython.lib.guisupport import start_event_loop_qt4, get_app_qt4, is_event_loop_running_qt4
4
+ from IPython.lib.guisupport import get_app_qt4, is_event_loop_running_qt4
5
5
 
6
6
  import os
7
7
  import sys
@@ -18,6 +18,39 @@ 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
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
+ new_params = list(_complete_and_expand_params(params, list(all_params().keys())).items())
43
+ amount = amount.subs(new_params)
44
+ if amount.is_number:
45
+ amount = float(amount.evalf())
46
+ de["computed_amount"] = True
47
+
48
+ de["amount"] = amount
49
+ de["formula"] = e.get("formula", None)
50
+ exs.append(de)
51
+ a["exchanges"] = exs
52
+ return a
53
+
21
54
  class QStandardItemRO(QtGui.QStandardItem):
22
55
  def __init__(self, *args, data=None, **kwargs):
23
56
  super().__init__(*args, **kwargs)
@@ -46,6 +79,9 @@ class TableModel(QtGui.QStandardItemModel):
46
79
  for k in ["name", "unit", "categories", "location", "amount", "formula"]
47
80
  ]
48
81
 
82
+ if "computed_amount" in e:
83
+ row[-2].setForeground(QtGui.QBrush(QtCore.Qt.GlobalColor.red))
84
+
49
85
  etype = e.get("type", "unknown")
50
86
  if etype == "emission":
51
87
  path = os.path.join(os.path.dirname(__file__), "icons", "emission.png")
@@ -73,6 +109,9 @@ class ActionMenu(QtGui.QMenu):
73
109
  self.action_explore = self.addAction("Explore")
74
110
  self.action_explore.triggered.connect(self.explore_triggered)
75
111
 
112
+ self.action_explore = self.addAction("Explore in new window")
113
+ self.action_explore.triggered.connect(self.explore_in_new_window_triggered)
114
+
76
115
  def copy_triggered(self):
77
116
  QtGui.QGuiApplication.clipboard().setText(self.index.data())
78
117
 
@@ -85,31 +124,82 @@ class ActionMenu(QtGui.QMenu):
85
124
  def explore_triggered(self):
86
125
  self.parentWidget().explore(self.index)
87
126
 
127
+ def explore_in_new_window_triggered(self):
128
+ self.parentWidget().explore_in_new_window(self.index)
129
+
130
+ class TabBar(QtGui.QTabBar):
131
+ def __init__(self):
132
+ super().__init__()
133
+
134
+ def tabSizeHint(self, index):
135
+ value = super().tabSizeHint(index)
136
+ return QtCore.QSize(200, value.height())
137
+
138
+ def minimumTabSizeHint(self, index):
139
+ value = super().minimumTabSizeHint(index)
140
+ return QtCore.QSize(100, value.height())
141
+
88
142
 
89
143
  class ActivityWindow(QtGui.QMainWindow):
90
- keep = dict()
144
+ keep = list()
91
145
 
92
- def __init__(self, act):
146
+ def __init__(self, activity_json, params=None):
93
147
  super().__init__()
94
- self.act = act
95
-
96
- data = activity_to_json(act)
148
+ self.tabs = dict()
149
+ self.xcount = 0
150
+ self.params = params
97
151
 
98
152
  self.setWindowTitle("Activity Viewer")
99
- self.setGeometry(100, 100, 800, 600)
153
+ self.setMinimumSize(QtCore.QSize(800, 600))
154
+
155
+ self.tabs_widget = QtGui.QTabWidget()
156
+ self.tabs_widget.setTabBar(TabBar())
157
+ self.tabs_widget.setTabsClosable(True)
158
+ self.tabs_widget.setMovable(True)
159
+ self.tabs_widget.tabCloseRequested.connect(self.close_tab)
160
+ self.tabs_widget.setElideMode(QtCore.Qt.TextElideMode.ElideRight)
161
+ self.setCentralWidget(self.tabs_widget)
162
+ self.add_activity(activity_json)
163
+
164
+ def add_activity(self, activity_json):
165
+ key = (activity_json["database"], activity_json["code"])
166
+ if key in self.tabs:
167
+ activity_widget = self.tabs[key]
168
+ self.tabs_widget.setCurrentWidget(activity_widget)
169
+ return
170
+
171
+ activity_widget = ActivityTab(self, activity_json)
172
+ self.tabs[activity_widget.activity_key] = activity_widget
173
+ self.tabs_widget.addTab(activity_widget, f"#{self.xcount} "+activity_json["name"])
174
+ self.tabs_widget.setCurrentWidget(activity_widget)
175
+ activity_widget.tree_view.setColumnWidth(0, 400)
176
+ self.xcount += 1
177
+
178
+ def close_tab(self, index):
179
+ w = self.tabs_widget.widget(index)
180
+ del self.tabs[w.activity_key]
181
+ self.tabs_widget.removeTab(index)
182
+
183
+ def closeEvent(self, ev):
184
+ ActivityWindow.keep.remove(self)
185
+ super().closeEvent(ev)
186
+
187
+ class ActivityTab(QtGui.QWidget):
188
+ def __init__(self, xparent, activity_json):
189
+ super().__init__()
190
+
191
+ self.xparent = xparent
192
+ self.activity_key = (activity_json["database"], activity_json["code"])
100
193
 
101
- # Create central widget and layout
102
- central_widget = QtGui.QWidget()
103
- self.setCentralWidget(central_widget)
104
194
  layout = QtGui.QVBoxLayout()
105
- central_widget.setLayout(layout)
195
+ self.setLayout(layout)
106
196
 
107
197
  grid = QtGui.QGridLayout()
108
198
  layout.addLayout(grid)
109
199
 
110
200
  for i, k in enumerate(["database", "name", "location", "unit", "categories", "type"]):
111
201
  grid.addWidget(QtGui.QLabel(f"{k}:"), i, 0)
112
- x = QtGui.QLabel(f"{str(data.get(k, '-'))}")
202
+ x = QtGui.QLabel(f"{str(activity_json.get(k, '-'))}")
113
203
  x.setTextInteractionFlags(QtCore.Qt.TextInteractionFlag.TextSelectableByMouse)
114
204
  grid.addWidget(x, i, 1)
115
205
  next_row = grid.rowCount()
@@ -134,7 +224,7 @@ class ActivityWindow(QtGui.QMainWindow):
134
224
  self.tree_view.setAlternatingRowColors(True)
135
225
 
136
226
  self.model = TableModel()
137
- self.model.load(data["exchanges"])
227
+ self.model.load(activity_json["exchanges"])
138
228
  self.tree_view.setModel(self.model)
139
229
  self.tree_view.doubleClicked.connect(self.doubleCliked)
140
230
  self.tree_view.setExpandsOnDoubleClick(False)
@@ -148,11 +238,6 @@ class ActivityWindow(QtGui.QMainWindow):
148
238
  self.action_menu = ActionMenu(self, index)
149
239
  self.action_menu.exec(self.tree_view.viewport().mapToGlobal(point))
150
240
 
151
- def closeEvent(self, ev):
152
- if self.act.key in ActivityWindow.keep:
153
- del ActivityWindow.keep[self.act.key]
154
- super().closeEvent(ev)
155
-
156
241
  def update_filter(self, *args):
157
242
  text = self.filter_edit.text()
158
243
  if self.ignore_case.isChecked():
@@ -173,11 +258,19 @@ class ActivityWindow(QtGui.QMainWindow):
173
258
  def explore(self, index):
174
259
  r = index.row()
175
260
  v = self.model.root.child(r, 0).data()
176
- show_activity(bw2data.get_activity((v["database"], v["code"])))
261
+ act = bw2data.get_activity((v["database"], v["code"]))
262
+ if self.xparent.params is None:
263
+ activity_json = activity_to_json(act)
264
+ else:
265
+ activity_json = activity_to_json_with_params(act, self.xparent.params)
266
+ self.xparent.add_activity(activity_json)
267
+
268
+ def explore_in_new_window(self, index):
269
+ r = index.row()
270
+ v = self.model.root.child(r, 0).data()
271
+ act = bw2data.get_activity((v["database"], v["code"]))
272
+ show_activity(act, self.xparent.params)
177
273
 
178
- def show(self, *args, **kwargs):
179
- super().show(*args, **kwargs)
180
- self.tree_view.setColumnWidth(0, 400)
181
274
 
182
275
  # Replace IPython version to one compatible with Qt6
183
276
  def start_event_loop_qt4(app=None):
@@ -194,7 +287,7 @@ def start_event_loop_qt4(app=None):
194
287
  else:
195
288
  app._in_event_loop = True
196
289
 
197
- def show_activity(act):
290
+ def show_activity(act, params=None):
198
291
 
199
292
  if 'matplotlib' in sys.modules:
200
293
  import matplotlib
@@ -204,9 +297,13 @@ def show_activity(act):
204
297
 
205
298
  app = get_app_qt4()
206
299
 
207
- if (window := ActivityWindow.keep.get(act.key, None)) is None:
208
- window = ActivityWindow(act)
209
- ActivityWindow.keep[act.key] = window
300
+ if params is None:
301
+ activity_json = activity_to_json(act)
302
+ else:
303
+ activity_json = activity_to_json_with_params(act, params)
304
+
305
+ window = ActivityWindow(activity_json, params)
306
+ ActivityWindow.keep.append(window)
210
307
  window.show()
211
308
 
212
309
  if not is_event_loop_running_qt4(app):
@@ -215,5 +312,5 @@ def show_activity(act):
215
312
  window.activateWindow()
216
313
 
217
314
  def close_all():
218
- for w in list(ActivityWindow.keep.values()):
315
+ for w in list(ActivityWindow.keep):
219
316
  w.close()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: brightway-basic-explorer
3
- Version: 0.9.dev2
3
+ Version: 0.9.dev4
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>
@@ -12,7 +12,7 @@ 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.dev2"
15
+ version = "0.9.dev4"
16
16
  dependencies = [ "ipython" ]
17
17
  requires-python = ">= 3.10"
18
18
  keywords = ["lca", "ecoinvent", "brightway"]