Skip to content

Cannot use write_image to save 3d figure on jupyter notebook on remote cluster #421

@dpanici

Description

@dpanici

Hi! I am using a Jupyter notebook on a remote cluster (on which I do NOT have sudo access as it is a shared computing resource of which I am only a user), and in trying to save a 3d figure using write_image I get this error:

---------------------------------------------------------------------------
CancelledError                            Traceback (most recent call last)
File ~/.conda/envs/desc-env/lib/python3.12/site-packages/choreographer/browser_async.py:151, in Browser.open(self)
    150     _logger.debug("Populating Targets")
--> 151     await self.populate_targets()
    152 except (BrowserClosedError, BrowserFailedError, asyncio.CancelledError) as e:

File ~/.conda/envs/desc-env/lib/python3.12/site-packages/kaleido/kaleido.py:223, in Kaleido.populate_targets(self)
    217 """
    218 Override the browser populate_targets to ensure the correct page.
    219 
    220 Is called automatically during initialization, and should only be called
    221 once ever per object.
    222 """
--> 223 await super().populate_targets()
    224 await self._conform_tabs()

File ~/.conda/envs/desc-env/lib/python3.12/site-packages/choreographer/browser_async.py:291, in Browser.populate_targets(self)
    290     raise BrowserClosedError("populate_targets() called on a closed browser")
--> 291 response = await self.send_command("Target.getTargets")
    292 if "error" in response:

File ~/.conda/envs/desc-env/lib/python3.12/site-packages/choreographer/protocol/devtools_async.py:222, in Target.send_command(self, command, params)
    221 session = self.get_session()
--> 222 return await session.send_command(command, params)

File ~/.conda/envs/desc-env/lib/python3.12/site-packages/choreographer/protocol/devtools_async.py:95, in Session.send_command(self, command, params)
     94 _logger.debug2(f"Full params: {str(params).replace('%', '%%')}")
---> 95 return await self._broker.write_json(json_command)

File ~/.conda/envs/desc-env/lib/python3.12/site-packages/choreographer/_brokers/_async.py:259, in Broker.write_json(self, obj)
    258     _logger.debug(f"Future for {key} deleted.")
--> 259 return await future

CancelledError: 

The above exception was the direct cause of the following exception:

BrowserDepsError                          Traceback (most recent call last)
Cell In[21], line 5
      2 fig = plot_3d(
      3 eq_opt.surface, "B*n", field=coils_opt, alpha=0.5, grid=LinearGrid(M=20, N=40, NFP=1, endpoint=True))  # pass in surface so the Bplasma is not computed, as it is vacuum
      4 plot_coils(coils_opt, fig=fig)
----> 5 fig.write_image(f"{dirname}/QA_eq_and_coils_{i}_3d.png")
      6 plot_2d(
      7 eq_opt.surface,
      8 "B*n",
      9 field=coils_opt,
     10 cmap="viridis",
     11 )
     12 plt.savefig(f"{dirname}/QA_eq_{i}_2d_Bn_error.png")    

File ~/.conda/envs/desc-env/lib/python3.12/site-packages/plotly/basedatatypes.py:3895, in BaseFigure.write_image(self, *args, **kwargs)
   3891     if kwargs.get("engine", None):
   3892         warnings.warn(
   3893             ENGINE_PARAM_DEPRECATION_MSG, DeprecationWarning, stacklevel=2
   3894         )
-> 3895 return pio.write_image(self, *args, **kwargs)

File ~/.conda/envs/desc-env/lib/python3.12/site-packages/plotly/io/_kaleido.py:510, in write_image(fig, file, format, scale, width, height, validate, engine)
    506 format = infer_format(path, format)
    508 # Request image
    509 # Do this first so we don't create a file if image conversion fails
--> 510 img_data = to_image(
    511     fig,
    512     format=format,
    513     scale=scale,
    514     width=width,
    515     height=height,
    516     validate=validate,
    517     engine=engine,
    518 )
    520 # Open file
    521 if path is None:
    522     # We previously failed to make sense of `file` as a pathlib object.
    523     # Attempt to write to `file` as an open file descriptor.

File ~/.conda/envs/desc-env/lib/python3.12/site-packages/plotly/io/_kaleido.py:380, in to_image(fig, format, width, height, scale, validate, engine)
    377         kopts["mathjax"] = defaults.mathjax
    379     # TODO: Refactor to make it possible to use a shared Kaleido instance here
--> 380     img_bytes = kaleido.calc_fig_sync(
    381         fig_dict,
    382         opts=dict(
    383             format=format or defaults.default_format,
    384             width=width or defaults.default_width,
    385             height=height or defaults.default_height,
    386             scale=scale or defaults.default_scale,
    387         ),
    388         topojson=defaults.topojson,
    389         kopts=kopts,
    390     )
    391 except ChromeNotFoundError:
    392     raise RuntimeError(PLOTLY_GET_CHROME_ERROR_MSG)

File ~/.conda/envs/desc-env/lib/python3.12/site-packages/kaleido/__init__.py:171, in calc_fig_sync(*args, **kwargs)
    169     return _global_server.call_function("calc_fig", *args, **kwargs)
    170 else:
--> 171     return _sync_server.oneshot_async_run(calc_fig, args=args, kwargs=kwargs)

File ~/.conda/envs/desc-env/lib/python3.12/site-packages/kaleido/_sync_server.py:131, in oneshot_async_run(func, args, kwargs)
    129 res = q.get()
    130 if isinstance(res, BaseException):
--> 131     raise res
    132 else:
    133     return res

File ~/.conda/envs/desc-env/lib/python3.12/site-packages/kaleido/_sync_server.py:122, in oneshot_async_run.<locals>.run(func, q, *args, **kwargs)
    119 def run(func, q, *args, **kwargs):
    120     # func is a closure
    121     try:
--> 122         q.put(asyncio.run(func(*args, **kwargs)))
    123     except BaseException as e:  # noqa: BLE001
    124         q.put(e)

File ~/.conda/envs/desc-env/lib/python3.12/asyncio/runners.py:194, in run(main, debug, loop_factory)
    190     raise RuntimeError(
    191         "asyncio.run() cannot be called from a running event loop")
    193 with Runner(debug=debug, loop_factory=loop_factory) as runner:
--> 194     return runner.run(main)

File ~/.conda/envs/desc-env/lib/python3.12/asyncio/runners.py:118, in Runner.run(self, coro, context)
    116 self._interrupt_count = 0
    117 try:
--> 118     return self._loop.run_until_complete(task)
    119 except exceptions.CancelledError:
    120     if self._interrupt_count > 0:

File ~/.conda/envs/desc-env/lib/python3.12/asyncio/base_events.py:664, in BaseEventLoop.run_until_complete(self, future)
    661 if not future.done():
    662     raise RuntimeError('Event loop stopped before Future completed.')
--> 664 return future.result()

File ~/.conda/envs/desc-env/lib/python3.12/site-packages/kaleido/__init__.py:101, in calc_fig(fig, path, opts, topojson, kopts)
     99 kopts = kopts or {}
    100 kopts["n"] = 1  # should we force this?
--> 101 async with Kaleido(**kopts) as k:
    102     return await k.calc_fig(
    103         fig,
    104         path=path,
    105         opts=opts,
    106         topojson=topojson,
    107     )

File ~/.conda/envs/desc-env/lib/python3.12/site-packages/choreographer/browser_async.py:167, in Browser.__aenter__(self)
    165 async def __aenter__(self) -> Self:
    166     """Open browser as context to launch on entry and close on exit."""
--> 167     await self.open()
    168     return self

File ~/.conda/envs/desc-env/lib/python3.12/site-packages/kaleido/kaleido.py:189, in Kaleido.open(self)
    187         page = PageGenerator(plotly=self._plotlyjs, mathjax=self._mathjax)
    188     page.generate_index(index)
--> 189 await super().open()

File ~/.conda/envs/desc-env/lib/python3.12/site-packages/choreographer/browser_async.py:157, in Browser.open(self)
    152 except (BrowserClosedError, BrowserFailedError, asyncio.CancelledError) as e:
    153     if (
    154         hasattr(self._browser_impl, "missing_libs")
    155         and self._browser_impl.missing_libs
    156     ):
--> 157         raise BrowserDepsError from e
    158     raise BrowserFailedError(
    159         "The browser seemed to close immediately after starting.",
    160         "You can set the `logging.Logger` level lower to see more output.",
    161         "You may try installing a known working copy of Chrome by running ",
    162         "`$ choreo_get_chrome`. It may be your copy auto-updated.",
    163     ) from e

BrowserDepsError: It seems like you are running a slim version of your operating system and are missing some common dependencies. The following command should install the required dependencies on most systems:

$ sudo apt update && sudo apt-get install libnss3 libatk-bridge2.0-0 libcups2 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1 libxkbcommon0 libpango-1.0-0 libcairo2 libasound2

If you have already run the above command and are still seeing this error, or the above command fails, consult the Kaleido documentation for operating system to install chromium dependencies.

For support, run the command `choreo_diagnose` and create an issue with its output.

The output of running choreo_diagnose is given in the attached .txt file. It seems to fail do to uv not being installed which seems like a random/unneeded dependency? I cannot sudo apt update anything on this cluster like the error message seems to say, so I am unsure how to proceed. Thanks!

choreo_diagnose_output.txt

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions