pyGSTi
pyGSTi copied to clipboard
ValueError: output array is read-only on report generation
Describe the bug When trying to generate a GST report, I get the titular ValueError.
To Reproduce Steps to reproduce the behavior: Attempt to generate a GST report with latest develop branch. Not sure if I can share pickled datasets, so I will avoid that for now. If issue is unclear, I will have time later in the week to see if I can reproduce this error with a fake/example dataset.
Environment (please complete the following information):
- pyGSTi version [0.9.14.1.post1.dev36+g8ed6a570a.develop.d20251209 (local install of develop branch in which this is the last commit)]
- python version [3.13.9]
- OS [e.g. OSX 15.5]
Additional context Here is the traceback, which is informative. Seems to have to do with eigenvalue computations?
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[4], line 15
13 index = qsplit.index("comp")
14 dirname = "./exp_gst_reports/" + "_".join(qsplit[index:])
---> 15 ro.write_html(dirname)
File ~/pygsti/pygsti/report/report.py:176, in Report.write_html(self, path, auto_open, link_to, connected, build_options, brevity, precision, resizable, autosize, single_file, verbosity)
173 toggles['BrevityLT' + str(k + 1)] = True
175 # Render sections
--> 176 qtys = self._build(build_options)
178 # TODO this really should be a parameter of this method
179 embed_figures = self._report_params.get('embed_figures', True)
File ~/pygsti/pygsti/report/report.py:91, in Report._build(self, build_options)
89 qtys = self._global_qtys.copy()
90 for section in self._sections:
---> 91 qtys.update(section.render(self._workspace, **full_params))
93 return qtys
File ~/pygsti/pygsti/report/section/gauge.py:31, in GaugeInvariantsGatesSection.render(self, workspace, results, dataset_labels, est_labels, embed_figures, **kwargs)
21 gi_switchboard = _create_single_metric_switchboard(
22 workspace, results, True, dataset_labels, est_labels, embed_figures
23 )
24 gr_switchboard = _create_single_metric_switchboard(
25 workspace, {}, False, [], embed_figures=embed_figures
26 )
28 return {
29 'metricSwitchboard_gi': gi_switchboard,
30 'metricSwitchboard_gr': gr_switchboard,
---> 31 **super().render(
32 workspace, gr_switchboard=gr_switchboard,
33 gi_switchboard=gi_switchboard,
34 dataset_labels=dataset_labels, est_labels=est_labels,
35 embed_figures=embed_figures, **kwargs
36 )
37 }
File ~/pygsti/pygsti/report/section/__init__.py:79, in Section.render(self, workspace, brevity, **kwargs)
55 def render(self, workspace, brevity=0, **kwargs):
56 """
57 Render this section's figures.
58
(...) 76 Key-value map of report quantities used for this section.
77 """
78 return {
---> 79 k: v(workspace, brevity=brevity, **kwargs)
80 for k, v in self._figure_factories.items()
81 if v.__figure_brevity_limit__ is None or brevity < v.__figure_brevity_limit__
82 }
File ~/pygsti/pygsti/report/section/gauge.py:48, in GaugeInvariantsGatesSection.final_model_eigenvalue_table(workspace, switchboard, confidence_level, ci_brevity, **kwargs)
46 @_Section.figure_factory(4)
47 def final_model_eigenvalue_table(workspace, switchboard=None, confidence_level=None, ci_brevity=1, **kwargs):
---> 48 return workspace.GateEigenvalueTable(
49 switchboard.mdl_gaugeinv, switchboard.mdl_target, _cri_gauge_inv(1, switchboard,
50 confidence_level, ci_brevity),
51 display=('evals', 'target', 'absdiff-evals', 'infdiff-evals', 'log-evals', 'absdiff-log-evals')
52 )
File <string>:2, in factoryfn(model, target_model, confidence_region_info, display, virtual_ops)
File ~/pygsti/pygsti/report/workspacetables.py:2461, in GateEigenvalueTable.__init__(self, ws, model, target_model, confidence_region_info, display, virtual_ops)
2411 def __init__(self, ws, model, target_model=None,
2412 confidence_region_info=None,
2413 display=('evals', 'rel', 'log-evals', 'log-rel', 'polar', 'relpolar'),
2414 virtual_ops=None):
2415 """
2416 Create table which lists and displays (using a polar plot)
2417 the eigenvalues of a model's gates.
(...) 2459 ReportTable
2460 """
-> 2461 super(GateEigenvalueTable, self).__init__(ws, self._create, model,
2462 target_model,
2463 confidence_region_info, display,
2464 virtual_ops)
File ~/pygsti/pygsti/report/workspace.py:2050, in WorkspaceTable.__init__(self, ws, fn, *args)
2047 self.tablefn = fn
2048 self.initargs = args
2049 self.tables, self.switchboards, self.sbSwitchIndices, self.switchpos_map = \
-> 2050 self.ws.switched_compute(self.tablefn, *self.initargs)
File ~/pygsti/pygsti/report/workspace.py:712, in Workspace.switched_compute(self, fn, *args)
710 key = "NA"; result = v; break
711 else:
--> 712 key, result = self.smartCache.cached_compute(fn, argVals)
714 if key not in storedKeys or key == 'INEFFECTIVE':
715 switchpos_map[pos] = len(resultValues)
File ~/pygsti/pygsti/baseobjs/smartcache.py:312, in SmartCache.cached_compute(self, fn, arg_vals, kwargs)
310 self.typesigs[name_key] = typesig
311 with _timed_block('call', times):
--> 312 self.cache[key] = fn(*arg_vals, **kwargs)
313 if "_filledarrays" in special_kwargs:
314 self.outargs[key] = tuple((arg_vals[i] if isinstance(i, int) else kwargs[i]
315 for i in special_kwargs['_filledarrays'])) # copy?
File ~/pygsti/pygsti/report/workspacetables.py:2573, in GateEigenvalueTable._create(self, model, target_model, confidence_region_info, display, virtual_ops)
2571 else:
2572 mx = target_model.sim.product(gl)
-> 2573 target_evals = _tools.eigenvalues(mx)
2575 if any([(x in display) for x in ('rel', 'log-rel', 'relpolar')]):
2576 if isinstance(gl, _baseobjs.Label) or isinstance(gl, str):
File ~/pygsti/pygsti/tools/matrixtools.py:816, in eigenvalues(m, assume_hermitian, assume_normal)
812 assume_hermitian = is_hermitian(m)
813 if assume_hermitian:
814 # Make sure it's Hermtian in exact arithmetic. This helps with
815 # reproducibility across different implementations of LAPACK.
--> 816 m += m.T.conj()
817 m /= 2
818 return _np.linalg.eigvalsh(m)
ValueError: output array is read-only