Skip to main content

Cards - Visualizing results

Metaflow Cards allows you to produce human readable reports in workflows. Use the following APIs to enable, customize, and access cards:

Retrieving cards

To retrieve a card after a run has finished, use the get_cards function e.g. in a notebook or the card get command on the CLI.

Since a task can contain multiple cards get_cards returns a container object, CardContainer, which holds Card objects corresponding to individual cards. Notably both CardContainer and Card objects contain a function that allow them to visualize cards in the notebook output cell automatically, so a single get_cards call can be used to show all cards of a step in a notebook.

get_cards(task, id, type, follow_resumed)

[source]

from metaflow.cards import get_cards

Get cards related to a Task.

Note that get_cards resolves the cards contained by the task, but it doesn't actually retrieve them from the datastore. Actual card contents are retrieved lazily either when the card is rendered in a notebook to when you call Card.get. This means that get_cards is a fast call even when individual cards contain a lot of data.

Parameters 

task: str or Task

A Task object or pathspec {flow_name}/{run_id}/{step_name}/{task_id} that uniquely identifies a task.

id: str, optional

The ID of card to retrieve if multiple cards are present.

type: str, optional

The type of card to retrieve if multiple cards are present.

follow_resumed: bool, default: True

If the task has been resumed, then setting this flag will resolve the card for the origin task.

Returns 

CardContainer

A list-like object that holds Card objects.

CardContainer()

[source]

CardContainer is an immutable list-like object, returned by get_cards, which contains individual Cards.

Notably, CardContainer contains a special _repr_html_ function which renders cards automatically in an output cell of a notebook.

The following operations are supported:

cards = get_cards(MyTask)

# retrieve by index
first_card = cards[0]

# check length
if len(cards) > 1:
    print('many cards present!')

# iteration
list_of_cards = list(cards)

Card represents an individual Metaflow Card, a single HTML file, produced by the card @card decorator. Cards are contained by CardContainer, returned by get_cards.

Note that the contents of the card, an HTML file, is retrieved lazily when you call Card.get for the first time or when the card is rendered in a notebook.

Attributes 

id

The ID of the card, if specified with @card(id=ID).

path

The path of the card in the datastore which uniquely identifies the card.

Returns

str Path to the card

Card.get(self)

[source]

Retrieves the HTML contents of the card from the Metaflow datastore.

Returns 

str

HTML contents of the card.

Card.view(self)

[source]

Opens the card in a local web browser.

This call uses Python's built-in webbrowser module to open the card.

Card components

You can customize the contents of a card easily using card components, a set of visual elements included in Metaflow which are documented below. See Easy Custom Reports with Card Components for instructions.

The components are added to cards in @step methods (or functions called from steps), using the current.card object.

Markdown

Markdown(text)

[source]

from metaflow.cards import Markdown

A block of text formatted in Markdown.

Example:

current.card.append(
    Markdown("# This is a header appended from `@step` code")
)
Parameters 

text: str

Text formatted in Markdown.

Image

Image(src, label)

[source]

from metaflow.cards import Image

An image.

Images can be created directly from PNG/JPG/GIF bytes, PIL.Image`s, or Matplotlib figures. Note that the image data is embedded in the card, so no external files are required to show the image.

Example: Create an Image from bytes:

current.card.append(
    Image(
        requests.get("https://www.gif-vif.com/hacker-cat.gif").content,
        "Image From Bytes"
    )
)

Example: Create an Image from a Matplotlib figure

import pandas as pd
import numpy as np
current.card.append(
    Image.from_matplotlib(
        pandas.DataFrame(
            np.random.randint(0, 100, size=(15, 4)),
            columns=list("ABCD"),
        ).plot()
    )
)

Example: Create an Image from a PIL Image

from PIL import Image as PILImage
current.card.append(
    Image.from_pil_image(
        PILImage.fromarray(np.random.randn(1024, 768), "RGB"),
        "From PIL Image"
    )
)
Parameters 

src: bytes

The image data in bytes.

label: str

Optional label for the image.

Image.from_matplotlib(plot, label)

[source]

Create an Image from a Matplotlib plot.

Parameters 

plot: matplotlib.figure.Figure or matplotlib.axes.Axes or matplotlib.axes._subplots.AxesSubplot

a PIL axes (plot) object.

label: str, optional

Optional label for the image.

Image.from_pil_image(pilimage, label)

[source]

Create an Image from a PIL image.

Parameters 

pilimage: PIL.Image

a PIL image object.

label: str, optional

Optional label for the image.

Artifact

Artifact(artifact, name, compressed)

[source]

from metaflow.cards import Artifact

A pretty-printed version of any Python object.

Large objects are truncated using Python's built-in reprlib.

Example:

from datetime import datetime
current.card.append(Artifact({'now': datetime.utcnow()}))
Parameters 

artifact: object

Any Python object.

name: str, optional

Optional label for the object.

compressed: bool, default: True

Use a truncated representation.

Table

Table(data, headers)

[source]

from metaflow.cards import Table

A table.

The contents of the table can be text or numerical data, a Pandas dataframe, or other card components: Artifact, Image, Markdown objects.

Example: Text and artifacts

from metaflow.cards import Table, Artifact
current.card.append(
    Table([
        ['first row', Artifact({'a': 2})],
        ['second row', Artifact(3)]
    ])
)

Example: Table from a Pandas dataframe

from metaflow.cards import Table
import pandas as pd
import numpy as np
current.card.append(
    Table.from_dataframe(
        pd.DataFrame(
            np.random.randint(0, 100, size=(15, 4)),
            columns=list("ABCD")
        )
    )
)
Parameters 

data: List[List[str or MetaflowCardComponent]], optional

List (rows) of lists (columns). Each item can be a string or a MetaflowCardComponent.

headers: List[str], optional

Optional header row for the table.

Table.from_dataframe(dataframe, truncate)

[source]

Create a Table based on a Pandas dataframe.

Parameters 

dataframe: Optional[pandas.DataFrame]

Pandas dataframe.

truncate: bool, default: True

Truncate large dataframe instead of showing all rows (default: True).

Defining a custom card

You can define custom cards types (T in @card(type=T)) by creating a Python package that includes a class that derives from MetaflowCard, documented below.

Find detailed instructions, a starter template, and an example of a simple custom card at https://github.com/outerbounds/metaflow-card-html.

MetaflowCard(options)

[source]

from metaflow.cards import MetaflowCard

Metaflow cards derive from this base class.

Subclasses of this class are called card types. The desired card type T is defined in the @card decorator as @card(type=T).

After a task with @card(type=T, options=S) finishes executing, Metaflow instantiates a subclass C of MetaflowCard that has its type attribute set to T, i.e. C.type=T. The constructor is given the options dictionary S that contains arbitrary JSON-encodable data that is passed to the instance, parametrizing the card. The subclass may override the constructor to capture and process the options.

The subclass needs to implement a render(task) method that produces the card contents in HTML, given the finished task that is represented by a Task object.

Parameters 

options: Dict

JSON-encodable dictionary containing user-definable options for the class.

Attributes 

type: str

Card type string. Note that this should be a globally unique name, similar to a Python package name, to avoid name clashes between different custom cards.

MetaflowCard.render(self, task)

[source]

Produce custom card contents in HTML.

Subclasses override this method to customize the card contents.

Parameters 

task: Task

A Task object that allows you to access data from the finished task and tasks preceding it.

Returns 

str

Card contents as an HTML string.