23
23
import contextlib
24
24
from collections import deque
25
25
from datetime import datetime
26
- import io
27
26
28
27
from qiskit .providers import Job , BaseJob , Backend , BaseBackend , Provider
29
28
from qiskit .result import Result
34
33
from .exceptions import ExperimentError , ExperimentEntryNotFound , ExperimentEntryExists
35
34
from .analysis_result import AnalysisResultV1 as AnalysisResult
36
35
from .json import NumpyEncoder , NumpyDecoder
37
- from .utils import (save_data , qiskit_version , plot_to_svg_bytes ,
38
- ThreadSafeOrderedDict , ThreadSafeList )
36
+ from .utils import (
37
+ save_data ,
38
+ qiskit_version ,
39
+ plot_to_svg_bytes ,
40
+ ThreadSafeOrderedDict ,
41
+ ThreadSafeList ,
42
+ )
39
43
40
44
LOG = logging .getLogger (__name__ )
41
45
@@ -166,12 +170,16 @@ def add_data(
166
170
data : Union [Result , List [Result ], Job , List [Job ], Dict , List [Dict ]],
167
171
post_processing_callback : Optional [Callable ] = None ,
168
172
** kwargs : Any ,
169
- ):
173
+ ) -> None :
170
174
"""Add experiment data.
171
175
172
176
Note:
173
177
This method is not thread safe and should not be called by the
174
- `post_processing` function.
178
+ `post_processing_callback` function.
179
+
180
+ Note:
181
+ If `data` is a ``Job``, this method waits for the job to finish
182
+ and calls the `post_processing_callback` function asynchronously.
175
183
176
184
Args:
177
185
data: Experiment data to add.
@@ -183,18 +191,16 @@ def add_data(
183
191
* List[Job]: Add data from the job results.
184
192
* Dict: Add this data.
185
193
* List[Dict]: Add this list of data.
186
- post_processing_callback: Callback function invoked when all pending
187
- jobs finish. This ``ExperimentData`` object is the only argument
194
+ post_processing_callback: Callback function invoked when data is
195
+ added. If `data` is a ``Job``, the callback is only invoked when
196
+ the job finishes successfully.
197
+ This ``ExperimentData`` object is the only argument
188
198
to be passed to the callback function.
189
199
**kwargs: Keyword arguments to be passed to the callback function.
190
200
Raises:
191
201
TypeError: If the input data type is invalid.
192
202
"""
193
- if isinstance (data , dict ):
194
- self ._add_single_data (data )
195
- elif isinstance (data , Result ):
196
- self ._add_result_data (data )
197
- elif isinstance (data , (Job , BaseJob )):
203
+ if isinstance (data , (Job , BaseJob )):
198
204
if self .backend and self .backend != data .backend ():
199
205
LOG .warning (
200
206
"Adding a job from a backend (%s) that is different "
@@ -219,13 +225,22 @@ def add_data(
219
225
)
220
226
if self .auto_save :
221
227
self .save ()
228
+ return
229
+
230
+ if isinstance (data , dict ):
231
+ self ._add_single_data (data )
232
+ elif isinstance (data , Result ):
233
+ self ._add_result_data (data )
222
234
elif isinstance (data , list ):
223
235
# TODO use loop instead of recursion for fewer save()
224
236
for dat in data :
225
237
self .add_data (dat )
226
238
else :
227
239
raise TypeError (f"Invalid data type { type (data )} ." )
228
240
241
+ if post_processing_callback is not None :
242
+ post_processing_callback (self , ** kwargs )
243
+
229
244
def _wait_for_job (
230
245
self ,
231
246
job : Union [Job , BaseJob ],
@@ -364,7 +379,10 @@ def add_figures(
364
379
if isinstance (figure , str ):
365
380
fig_name = figure
366
381
else :
367
- fig_name = f"figure_{ self .experiment_id } _{ datetime .now ().isoformat ()} "
382
+ fig_name = (
383
+ f"figure_{ self .experiment_id [:8 ]} _"
384
+ f"{ datetime .now ().isoformat ()} _{ len (self ._figures )} "
385
+ )
368
386
else :
369
387
fig_name = figure_names [idx ]
370
388
@@ -387,6 +405,7 @@ def add_figures(
387
405
if save and service :
388
406
if HAS_MATPLOTLIB :
389
407
from matplotlib import pyplot
408
+
390
409
if isinstance (figure , pyplot .Figure ):
391
410
figure = plot_to_svg_bytes (figure )
392
411
data = {
@@ -661,6 +680,7 @@ def save_all(self, service: Optional["ExperimentServiceV1"] = None) -> None:
661
680
for name , figure in self ._figures .items ():
662
681
if HAS_MATPLOTLIB :
663
682
from matplotlib import pyplot
683
+
664
684
if isinstance (figure , pyplot .Figure ):
665
685
figure = plot_to_svg_bytes (figure )
666
686
data = {"experiment_id" : self .experiment_id , "figure" : figure , "figure_name" : name }
0 commit comments