Creating plots in a task type

In Python for example Example.Basic.PlotXY uses Core.Python.matplotlib and Core.Python.seaborn to generate a simple plot:

# Avoid requiring tkinter
import matplotlib
matplotlib.use('agg', force=True)
import matplotlib.pyplot as plt

import pandas
from pandas.api.types import is_numeric_dtype # type: ignore
import seaborn

import xfworkerutil


worker = xfworkerutil.XFWorkerJob()

inputs = worker.job['inputs']
x_column_name = inputs['x_column_name']
y_column_name = inputs['y_column_name']
x_column_label = inputs['x_column_label']
y_column_label = inputs['y_column_label']
x_scale = inputs['x_scale']
y_scale = inputs['y_scale']
group_column_name = inputs['group_column_name']
palette = inputs['palette']
stylesheet = inputs['stylesheet']
custom_style = inputs['custom_style']
mode = inputs['mode']

plt.style.use(stylesheet)
if custom_style is not None:
    custom_style_path = worker.create_temp_path("custom_style.rc")
    custom_style_path.write_text(custom_style)
    matplotlib.rc_file(custom_style_path, use_default_template=False)

if group_column_name is not None and mode not in ('basic', 'lineplot'):
    worker.error("Grouping is only supported in basic or lineplot mode.")

# Download input files
table_path = worker.download_input_file(inputs['table'])

plot_path = worker.create_related_path(table_path, '_plot.png')
pdf_path = worker.create_related_path(table_path, '_plot.pdf')

# Plot
data = pandas.read_csv(str(table_path))

if x_column_name is None:
    x_column_name = [name for name in data.columns if name != y_column_name and is_numeric_dtype(data[name])][0]
if y_column_name is None:
    y_column_name = [name for name in data.columns if name != x_column_name and is_numeric_dtype(data[name])][0]

if palette == 'BlackGray':
    palette = ['black', 'gray']

fig = None
if mode == 'ci+univariate':
    plot_grid = seaborn.jointplot(x=x_column_name, y=y_column_name, data=data, kind="reg")
    axes = plot_grid.ax_joint
    fig = plot_grid
elif mode in ['regression', 'ci']:
    ci = None
    if mode == 'ci':
        ci = 95
    axes = seaborn.regplot(x=x_column_name, y=y_column_name, data=data, ci=ci)
elif mode == 'lineplot':
    axes = seaborn.lineplot(x=x_column_name, y=y_column_name, data=data, hue=group_column_name, palette=palette)
else: # basic
    axes = seaborn.scatterplot(x=x_column_name, y=y_column_name, data=data, hue=group_column_name, palette=palette)

axes.set_xscale(x_scale)
axes.set_yscale(y_scale)

if x_column_label is not None: axes.set(xlabel=x_column_label)
if y_column_label is not None: axes.set(ylabel=y_column_label)

if fig is None:
    fig = axes.get_figure()
fig.savefig(str(plot_path))
fig.savefig(str(pdf_path))

# Upload output files
worker.upload_output_file(plot_path)
worker.upload_output_file(pdf_path)

# Save outputs
outputs = {
    "plot": worker.create_output_bitmap(plot_path.name),
    "pdf": worker.create_output_foreign_file(pdf_path.name),
}
worker.finish(outputs)

The plot is stored as an output of type Bitmap.

Chart Report

Also consider using chart reports in XF Desktop for interactive plots.

See also Using R in a task type / Using MATLAB in a task type.