Iframe won't display altair chart on data with more than 1750 rows

I’m trying to use an iFrame to display an altair chart of a machine learning model’s results. The data used for the model can be up to 20000 rows, but the iFrame will not display anything unless the data is first sampled down to 1750 rows.

All of the code to run the model and construct the graphs is in an Uplink server and I am using alt.data_transformers.disable_max_rows() on that server. When I run the model there, everything displays fine. But when I call the function from Anvil, the iFrame displays nothing. When I go back to the Uplink server and sample the data down to 1750, it works in Anvil. Is this some sort of limitation with how Anvil uses altair?

I don’t claim to fully understand, but I doubt there is any Anvil limit on what you can display in an iFrame. I suspect the issue is similar to others you’ve reported, some kind of timeout in the connection between Colab and Anvil. Do you get the same issues if you run the Uplink code on your local machine, where you have more control of what’s going on? Otherwise, providing more details (like a clone link) might help others better diagnose with you.

It is a little complicated to diagnose, but I’m skeptical that it’s a timeout or connection issue. No errors are displayed and having the Uplink server return objects other than altiar succeeds without issue.

I have managed to play around with this more and I don’t think it’s the number of rows exactly that is the problem, but rather just the number of data points. Increasing the number of columns also seems to produce this problem.

If you want to dig in more, I was able to reproduce the issue in the ‘Altair in Anvil’ demo from the documentation. The clone link to that is below. I don’t have a paid account, so can’t use Full Python3 in the server module, so it might be worth it to have someone with that access try this out. Basically, I just copied the code from the server module to an Uplink server and ran it that way.

You can change the line x = np.arange(0.0, 5.0, 0.02) to control the number of rows in the data. I used something like this so I could directly define the number of rows:
x = np.arange(0.0, 100000, 1). The 100000 is the number of rows, and that’s where the iFrame starts failing for me in this example. The data I’m using for my app is much more complex, with several columns of float values, so that is why I think the iFrame fails with fewer rows in my app.

https://anvil.works/build#clone:CFRUWSM6PQ6JUUXH%3DSX4SACDSXBB4UOIVEVPWXH55|CGRHCQWKA44IMZI2%3DOSDATSKED6H2EZ5P4U52BSUH

1 Like

In an added bit of testing, I changed the return line of the server code to this: return (anvil.media.from_file('/tmp/altair.html', 'text/html'), "Chart should be visible"). This lets me return a message at the same time as the chart. Then add a ‘label’ to the app and use these lines to call the server function and display both chart and message:

    # Any code you write here will run when the form opens.
    full_output = anvil.server.call('make_plot')
    chart_obj = full_output[0]
    message = full_output[1]
    self.i_frame_1.url = chart_obj.get_url(True)
    self.label_1.text = message

This will make it so that as soon as Anvil gets the chart back from the Uplink server, it will display the message letting you know the function completed successfully.

The full Uplink Server code is below. This results in the label displaying “Chart should be visible”, but having an empty iFrame.

import anvil.server
import anvil.media

import altair as alt
import numpy as np
import pandas as pd


@anvil.server.callable
def make_plot():
  # Make a nice wiggle
  x = np.arange(0.0, 100000, 1)
  df = pd.DataFrame({
    'x': x,
    'y': np.exp(-x) * np.cos(2*np.pi*x),
  })

  # Plot it in the usual Altair way
  chart = alt.Chart(df).mark_line().encode(
    x='x',
    y='y',
  )
  
  chart.save('/tmp/altair.html')

  return (anvil.media.from_file('/tmp/altair.html', 'text/html'), "Chart should be visible")

anvil.server.wait_forever()
1 Like

Well, that will (er, should) teach me to comment on things I don’t understand. I can indeed replicate the issue you describe, using a Full Python Server Module rather than Uplink:
https://anvil.works/build#clone:UZKXKXBQKWYI2XWV=O2J4VX275K7XEXAFGYI7MQHR

If I change line 12 of the Server Module back to: x = np.arange(0.0, 100000, 1), the chart no longer displays.

Hopefully your providing this replication information will help others (@patricia ?) troubleshoot the issue with you.

edit: Apologies for my hacked-together clone. I didn’t realize that your clone link had saved two new apps (with the iframe intended to be a dependency only).

1 Like

Indeed! And I wouldn’t sweat commenting on things without fully understanding them. Your comments helped me figure out a better description of the issue. I’m doing this for a school project, and I got confirmation from my instructors that using smaller samples and creating a sort of ‘demo’ app is just fine. So I’m not stressing about these issues anymore. But figuring out how to get Anvil working with this sort of project would be neat. I really like it as an app-building platform.

2 Likes