Select to view content in your preferred language

Turn-off chart title with Python in ArcGIS Pro 3.2

437
9
08-12-2024 05:09 PM
KITEfejlesztes
Emerging Contributor

Hi, I would like to maximize the size of the box-plot graphs by turning off the automatic Chart titles, which I don't need at all, so that I can print the 5 graph images pasted into the layout on 1 pdf sheet. The script snippet is part of a python toolbox and the full boxplot images will be successfully generated if I don't try to turn the Chart title off. However, if I paste my attempts at CIM definition it runs to error, or nothing happens. How can this be resolved within the script toolbox?

plot_list= [
        {"name": "DEM_plot", "yAxis": "DEM", "ytitle": "DEM (m)", "place": 272},
        {"name": "SLOPE_plot", "yAxis": "slope_p", "ytitle": "SLOPE (%)", "place": 216},
        {"name": "Wet_plot", "yAxis": "Wet", "ytitle": "Wetness", "place": 160},
        {"name": "NDVI_plot", "yAxis": "NDVI_mean", "ytitle": "NDVI", "place": 104},
        {"name": "Temp_plot", "yAxis": "temp_n", "ytitle": "Temp (C)", "place": 58},
    ]
    for types in plot_list:
        arcpy.AddMessage(types["name"])
        censusLayer = (lyr_plot)
        c = arcpy.Chart("{}".format(types["name"]))
        c.type = 'boxPlot'
        c.xAxis.field = 'SS_GROUP'
        c.xAxis.title = "Zone"
        c.yAxis.field = "{}".format(types["yAxis"])
        c.yAxis.title = "{}".format(types["ytitle"])
        c.showOutliers = False
        c.dataSource = lyr_plot
        c.addToLayer(censusLayer)
        c_cim= lyr_plot.getDefinition('V3') #from this point do not work
        for f in c_cim.charts:
            f.generalProperties.showTitle=False
        lyr_plot.setDefinition(c_cim) #until this point
        c.exportToSVG(os.path.join(output_folder,"boxplot{}.svg".format(tipus["name"])), width=850, height=270)
        aprx.createPictureElement(lyt_hat, MakeRec_UL(5, int("{}".format(types["place"])), 200, 55), os.path.join(output_folder,"boxplot{}.svg".format(tipus["name"])))
0 Kudos
9 Replies
DanPatterson
MVP Esteemed Contributor

Have you looked at the arcpy charts module? (Box example below).  I don't see chart in the cim

Box—ArcGIS Pro | Documentation


... sort of retired...
KITEfejlesztes
Emerging Contributor

This is the documentation I tried to use

https://github.com/Esri/cim-spec/blob/main/docs/v3/CIMCharts.md

search: CIMChartGeneralProperties

But I don't know what I typed wrong that didn't work

DanPatterson
MVP Esteemed Contributor

wild guess, but it appears that the types are supposedly json, so maybe the boolean is false not False.

otherwise, out of ideas, since they don't provide examples and I don't use cim much at all


... sort of retired...
0 Kudos
ChristopherAllen
Esri Contributor

Hi @KITEfejlesztes ,

Thanks for the question! I tried to run a similar workflow and all of the chart titles were turned off correctly when updating the chart CIM as per your example. You said that sometimes you'll see an error when trying to run the code that updates the CIM definition. Would you be able to share the error message?

Thanks,

Chris

0 Kudos
KITEfejlesztes
Emerging Contributor

I tried several times to modify the code and none of them worked. I can't remember exactly which version of my code it was writing the error message for - but it was about not being able to export CIMGraph elements to svg. With this CIM code snippet, it only works for me if a manually created graph is already open in the map window and I manually type these 4 lines in the Python window, then it does it, it turns off the title. But if it's all inside a script tool nothing happens, the graph image appears on the pdf with the automatic title.

0 Kudos
KITEfejlesztes
Emerging Contributor

The same happens when I try to use the CIM sample examples published by Jeff Barrette ESRI. When the map is in the view and I type the commands line by line in the python window, it works and turns off or modifies the element. However, if I paste the full code into the python window and run it that way, there is no change to the element. Moreover, I would do all this with a geoprocess flow within the arcgis script toolbox. I create layers and insert them into a project with specified settings and I would make the CIM changes on them. What could be the reason for this, is there any way to solve this?

0 Kudos
ChristopherAllen
Esri Contributor

Hi @KITEfejlesztes 

Thanks for the follow up, and apologies for the delay. The suggested way to add charts to an output in a script tool is to set the `charts` property on the output parameter. This approach is described more in this blog post. In this context, the charts will only be added to the output after the `execute` method is run. So you'd want to do the CIM manipulation in the `postExecute` method that's run after the `execute` method. Here's a code sample that should help illustrate the above points:

# -*- coding: utf-8 -*-

import arcpy

class Toolbox:
    def __init__(self):
        self.label = "Toolbox"
        self.alias = "Toolbox"

        self.tools = [AddBoxPlots]
        
class AddBoxPlots:
    def __init__(self):
        self.label = "AddBoxPlots"
        self.description = ""

    def getParameterInfo(self):
        input_lyr = arcpy.Parameter(
            displayName="Input Layer",
            name="input_lyr",
            datatype="GPFeatureLayer",
            parameterType="Required",
            direction="Input"
        )

        output_lyr = arcpy.Parameter(
            displayName="Output Layer",
            name="output_lyr",
            datatype="GPFeatureLayer",
            parameterType="Derived",
            direction="Output"
        )
        output_lyr.parameterDependencies = ['input_lyr']
        output_lyr.schema.clone = True
           
        return [input_lyr, output_lyr]
    
    def isLicensed(self):
        return True
    
    def execute(self, parameters, messages):
        """ Create charts and add to output. """
        output_lyr = parameters[1]

        box1 = arcpy.charts.Box(y='field1')
        box2 = arcpy.charts.Box(y='field2')

        # add charts to output layer
        output_lyr.charts = [box1, box2]

    def postExecute(self, parameters):
        """ Update all chart CIM to make sure titles are turned off. """
       
        input_lyr = arcpy.mp.ArcGISProject('current').activeMap.listLayers(parameters[0].value)[0]
        cim = input_lyr.getDefinition('V3')
        
        for cim_chart in cim.charts:
            cim_chart.generalProperties.showTitle = False

        input_lyr.setDefinition(cim)

        # TODO: Add charts to layout as chart frames

 

In this scenario you would add the charts to the layout in the `postExecute` method after you update the CIM. However, in this method you no longer have access to the chart objects so unfortunately you are unable to export the charts to SVG using the `exportToSVG` method as per your original code sample. Thus the preferred way to add the charts to a layout would be to add them as chart frames, but in Python this currently needs to be done through the CIM and I don't have a code sample handy. I try to will follow up as soon as possible with a full code sample that fills in the missing part here (adding the charts as chart frames to the layout).

Thanks,

Chris

0 Kudos
KITEfejlesztes
Emerging Contributor

Hi ChristopherAllen

Thank you for the detailed description. Unfortunately, the real purpose of making a pdf book is to make a multi-page pdf with maps using one tool. Then based on that, we will definitely need 2 tools.

0 Kudos
ChristopherAllen
Esri Contributor

Hi @KITEfejlesztes ,

Thanks for the additional context. Sorry to hear the suggested workflow is difficult to integrate into your process. 

Another idea that might work with your existing code would be to try simply setting the `title` property of the chart object to an empty string:

 

 

c.title = ''

 

 

I believe this should give you very similar results and should be straightforward to try. And this approach would allow you to bypass the CIM altogether.

Thanks!

Chris   

0 Kudos