Difficulties to use PropertyGroup in python plugin of a filter

Hello Paraview team.

I am trying to write a python plugin which creates a filter to plot data in a customized way. To do that, I used the paraview.util.vtkAlgorithm after looking at PythonAlgorithmExamples.py and the plugins documentation.
I have already achieved a first version of this filter with some widgets using @smproperty and @smdomain decorators like checkboxes, dropdown lists etc … which works fine.

My goal is now to add more functionnalities and to create a better organization of my widgets like in PlotData (see picture at the bottom). To do so, I am trying to use what was presented in this topic : Controlling the order that widgets appear in the GUI for a Python algorithm plugin - ParaView Support - ParaView

I need to use “PropertyGroup” but I did not find documentation regarding its use in Python plugins. And when I try to do it by myself, it seems that I am using it wrong in my code below, which tries to reproduce the XML filter of the XYChartRepresentation :

 @smproperty.intvector(name="Visibility", default_values=1, number_of_elements=1, panel_visibility="never")
    @smdomain.xml("""<BooleanDomain name="bool" />""")
    def SetVisibility(self, name):
        self.Modified()

    @smproperty.intvector(name="CompositeDataSetIndex", default_values=1, number_of_elements=1, number_of_elements_per_command=1, panel_visibility="default", repeat_command="1")
    @smdomain.xml("""<CompositeTreeDomain mode="leaves" name="tree">
                        <RequiredProperties>
                            <Property function="Input" name="Input" />
                        </RequiredProperties>
                    </CompositeTreeDomain>""")
    def AddCompositeDataSetIndex(self, name):
        self.Modified()

    @smproperty.intvector(name="AttributeType", default_values=0, number_of_elements=1)
    @smdomain.xml("""<FieldDataDomain enable_field_data="1" name="enum">
                        <RequiredProperties>
                            <Property function="Input" name="Input" />
                        </RequiredProperties>
                    </FieldDataDomain>""")
    def SetFieldAssociation(self, attr):
        self.Modified()

    @smproperty.stringvector(name="XArrayName", default_values=" ", number_of_elements=1)
    @smdomain.xml("""
                <ChartSeriesListDomain name="array_list" hide_partial_arrays="1">
                    <RequiredProperties>
                        <Property function="Input" name="Input" />
                        <Property function="FieldDataSelection" name="AttributeType" />
                    </RequiredProperties>
                </ChartSeriesListDomain>""")
    def SetDataForXAxisName(self, name):
        self._dataForXAxisName = name
        self.Modified()

    @smproperty.stringvector(name="SeriesVisibility", element_types=[2, 0], number_of_elements_per_command=2, repeat_command="1")
    @smdomain.xml("""<ChartSeriesSelectionDomain name="array_list" default_mode="visibility">
                        <RequiredProperties>
                            <Property function="Input" name="Input" />
                            <Property function="FieldDataSelection" name="AttributeType" />
                            <Property function="CompositeIndexSelection" name="CompositeDataSetIndex" />
                        </RequiredProperties>
                    </ChartSeriesSelectionDomain>""")
    def SetSeriesVisibility(self, name):
        self.Modified()

    @smproperty.stringvector(name="SeriesLabel", element_types=[2, 2], number_of_elements_per_command=2, repeat_command="1")
    @smdomain.xml("""<ChartSeriesSelectionDomain name="array_list" default_mode="label">
                        <RequiredProperties>
                            <Property function="Input" name="Input" />
                            <Property function="FieldDataSelection" name="AttributeType" />
                            <Property function="CompositeIndexSelection" name="CompositeDataSetIndex" />
                        </RequiredProperties>
                    </ChartSeriesSelectionDomain>""")
    def SetLabel(self, name):
        self.Modified()

    @smproperty.stringvector(name="SeriesColor", element_types=[2, 1, 1, 1], number_of_elements_per_command=4, repeat_command="1")
    @smdomain.xml("""<ChartSeriesSelectionDomain name="array_list" default_mode="color">
                        <RequiredProperties>
                            <Property function="Input" name="Input" />
                            <Property function="FieldDataSelection" name="AttributeType" />
                            <Property function="CompositeIndexSelection" name="CompositeDataSetIndex" />
                        </RequiredProperties>
                    </ChartSeriesSelectionDomain>""")
    def SetColor(self, name):
        self.Modified()

    @smproperty.stringvector(name="SeriesPlotCorner", element_types=[2, 0], number_of_elements_per_command=2, repeat_command="1")
    @smdomain.xml("""<ChartSeriesSelectionDomain name="array_list" default_mode="value" default_value="0">
                        <RequiredProperties>
                            <Property function="Input" name="Input" />
                            <Property function="FieldDataSelection" name="AttributeType" />
                            <Property function="CompositeIndexSelection" name="CompositeDataSetIndex" />
                        </RequiredProperties>
                    </ChartSeriesSelectionDomain>""")
    def SetAxisCorner(self, name):
        self.Modified()

    @smproperty.stringvector(name="SeriesLineStyle", element_types=[2, 0], number_of_elements_per_command=2, repeat_command="1")
    @smdomain.xml("""<ChartSeriesSelectionDomain name="array_list" default_mode="value" default_value="1">
                        <RequiredProperties>
                            <Property function="Input" name="Input" />
                            <Property function="FieldDataSelection" name="AttributeType" />
                            <Property function="CompositeIndexSelection" name="CompositeDataSetIndex" />
                        </RequiredProperties>
                    </ChartSeriesSelectionDomain>""")
    def SetLineStyle(self,name):
        self.Modified()

    @smproperty.stringvector(name="SeriesLineThickness", element_types=[2, 0], number_of_elements_per_command=2, repeat_command="1")
    @smdomain.xml("""<ChartSeriesSelectionDomain name="array_list" default_mode="value" default_value="2">
                        <RequiredProperties>
                            <Property function="Input" name="Input" />
                            <Property function="FieldDataSelection" name="AttributeType" />
                            <Property function="CompositeIndexSelection" name="CompositeDataSetIndex" />
                        </RequiredProperties>
                    </ChartSeriesSelectionDomain>""")
    def SetLineThickness(self,name):
        self.Modified()

    @smproperty.stringvector(name="SeriesMarkerStyle", element_types=[2, 0], number_of_elements_per_command=2, repeat_command="1")
    @smdomain.xml("""<ChartSeriesSelectionDomain name="array_list" default_mode="value" default_value="0">
                        <RequiredProperties>
                            <Property function="Input" name="Input" />
                            <Property function="FieldDataSelection" name="AttributeType" />
                            <Property function="CompositeIndexSelection" name="CompositeDataSetIndex" />
                        </RequiredProperties>
                    </ChartSeriesSelectionDomain>""")
    def SetMarkerStyle(self, name):
        self.Modified()
        
    @smproperty.doublevector(name="Color", default_values=[1.0, 0.0, 1.0], number_of_elements=3, panel_visibility="never")
    @smdomain.xml("""<DoubleRangeDomain max="1 1 1" min="0 0 0" name="range" />
                    <Hints>
                        <PropertyLink type="ColorPalette" property="SelectionColor" />
                    </Hints>""")
    def SetSelectionColor(self, name, name2, name3):
        self.Modified()

    @smproperty.xml(xmlstr="""<PropertyGroup label="Series Parameters" panel_widget="SeriesEditor" panel_visibility="default">
                        <Property name="SeriesVisibility" function="Series_Visibility"/>
                        <Property name="SeriesColor" function="Series_Color"/>
                        <Property name="SeriesLineThickness" function="Series_LineThickness"/>
                        <Property name="SeriesLineStyle" function="Series_LineStyle"/>
                        <Property name="SeriesLabel" function="Series_Label"/>
                        <Property name="SeriesMarkerStyle" function="Series_MarkerStyle"/>
                        <Property name="SeriesPlotCorner" function="Series_PlotCorner"/>
                    </PropertyGroup>""")
    def GroupSeriesParameters(self,name):
        self.Modified()

But I unfortunately receive this warning for every property :

... vtkSMPropertyGroup (0x28f2070): Failed to locate property 'SeriesVisibility' for PropertyGroup. Skipping.
... vtkSMPropertyGroup (0x28f2070): Failed to locate property 'SeriesColor' for PropertyGroup. Skipping.
...

Could you help me with that please ?
Have a great day

I’m afraid this is not supported by python plugins yet.

https://gitlab.kitware.com/paraview/paraview/-/issues/21493

Alex, since you are trying to use the work-around described in the discourse post, you should be able to get this to work. It does look like the sorting-order issue is still causing you a problem, though. You added the PropertyGroup XML to a method named GroupSeriesParameters, and if I’m reading this correctly, that means that it will be sorted as a “G”, which means it’s before the Set methods you want to refer to.

Does it work if you change the python method name to ZZGroupSeriesParameters ?

Thank you for your answers @mwestphal and @aron.helser , I have been able to make some progress by organizing the methods alphabetically, which corrected the “Failed to locate property” warning.

But I am having one last problem with the SeriesEditor panel widget.
As you can see in the picture, I managed to access the Row Data of my file and I am able to select in “X Array Name” which column I want to use for the X axis.
But when it comes to the panel widget, it does not display the columns name with the possibility to change the visibility, the color etc …

Could you help me find what I am missing for it to work please ? I have used this code which is a rewriting of your xml file : Remoting/Views/Resources/views_and_representations.xml · aa69a43734669d46e1d6f500e8e1fb0674134fad · ParaView / ParaView · GitLab (kitware.com)

@smproperty.intvector(name="Visibility", default_values=1, number_of_elements=1, panel_visibility="never")
    @smdomain.xml("""<BooleanDomain name="bool" />""")
    def aSetVisibility(self, name):
        self.Modified()

    @smproperty.intvector(name="ForceUseCache",  default_values=0, is_internal=1, number_of_elements=1)
    @smdomain.xml("""<BooleanDomain name="bool"/>""")
    def aSetForceUseCache(self, name):
        self.Modified()

    @smproperty.doublevector(name="ForcedCacheKey", default_values="none", is_internal=1, number_of_elements=1)
    @smdomain.xml("""<DoubleRangeDomain name="range"/>""")
    def aSetForcedCacheKey(self, name):
        self.Modified()

    @smproperty.intvector(name="CompositeDataSetIndex", default_values=1, number_of_elements=1, number_of_elements_per_command=1, panel_visibility="default", repeat_command=1)
    @smdomain.xml("""<CompositeTreeDomain mode="leaves" name="tree">
                        <RequiredProperties>
                            <Property function="Input" name="Input" />
                        </RequiredProperties>
                    </CompositeTreeDomain>
                    <Hints>
                        <!-- we don't want to show this property, except for MBs. -->
                        <PropertyWidgetDecorator type="InputDataTypeDecorator"
                            mode="visibility" name="vtkMultiBlockDataSet" />
                    </Hints>""")
    def bAddCompositeDataSetIndex(self, name):
        self.Modified()

    @smproperty.intvector(name="AttributeType", default_values=0, number_of_elements=1)
    @smdomain.xml("""<FieldDataDomain enable_field_data="1" name="enum">
                        <RequiredProperties>
                            <Property function="Input" name="Input" />
                        </RequiredProperties>
                    </FieldDataDomain>""")
    def cSetFieldAssociation(self, attr):
        self.Modified()

    @smproperty.stringvector(name="XArrayName", default_values=" ", number_of_elements=1)
    @smdomain.xml("""
                <ChartSeriesListDomain name="array_list" hide_partial_arrays="1">
                    <RequiredProperties>
                        <Property function="Input" name="Input" />
                        <Property function="FieldDataSelection" name="AttributeType" />
                    </RequiredProperties>
                </ChartSeriesListDomain>""")
    def dSetDataForXAxisName(self, name):
        self._dataForXAxisName = name
        self.Modified()

    @smproperty.stringvector(name="SeriesVisibility", element_types="2 0", number_of_elements_per_command=2, repeat_command=1)
    @smdomain.xml("""<ChartSeriesSelectionDomain name="array_list" default_mode="visibility" hide_partial_arrays="0">
                        <RequiredProperties>
                            <Property function="Input" name="Input" />
                            <Property function="FieldDataSelection" name="AttributeType" />
                            <Property function="CompositeIndexSelection" name="CompositeDataSetIndex" />
                        </RequiredProperties>
                    </ChartSeriesSelectionDomain>
                    <Hints>
                    <!-- when present, the SeriesEditor widget will allow user to
                    re-order the series which will affect the rendered plot -->
                    <SeriesEditor supports_reordering="1" />
                    </Hints>""")
    def eSetSeriesVisibility(self, name):
        self.Modified()

    @smproperty.stringvector(name="SeriesLabel", element_types="2 2", number_of_elements_per_command=2, repeat_command=1)
    @smdomain.xml("""<ChartSeriesSelectionDomain name="array_list" default_mode="label" hide_partial_arrays="0">
                        <RequiredProperties>
                            <Property function="Input" name="Input" />
                            <Property function="FieldDataSelection" name="AttributeType" />
                            <Property function="CompositeIndexSelection" name="CompositeDataSetIndex" />
                        </RequiredProperties>
                    </ChartSeriesSelectionDomain>""")
    def fSetLabel(self, name):
        self.Modified()

    @smproperty.stringvector(name="SeriesColor", element_types="2 1 1 1", number_of_elements_per_command=4, repeat_command=1)
    @smdomain.xml("""<ChartSeriesSelectionDomain name="array_list" default_mode="color" hide_partial_arrays="0">
                        <RequiredProperties>
                            <Property function="Input" name="Input" />
                            <Property function="FieldDataSelection" name="AttributeType" />
                            <Property function="CompositeIndexSelection" name="CompositeDataSetIndex" />
                        </RequiredProperties>
                    </ChartSeriesSelectionDomain>""")
    def gSetColor(self, name):
        self.Modified()

    @smproperty.stringvector(name="SeriesPlotCorner", element_types="2 0", number_of_elements_per_command=2, repeat_command=1)
    @smdomain.xml("""<ChartSeriesSelectionDomain name="array_list" default_mode="value" default_value="0" hide_partial_arrays="0">
                        <RequiredProperties>
                            <Property function="Input" name="Input" />
                            <Property function="FieldDataSelection" name="AttributeType" />
                            <Property function="CompositeIndexSelection" name="CompositeDataSetIndex" />
                        </RequiredProperties>
                    </ChartSeriesSelectionDomain>""")
    def hSetAxisCorner(self, name):
        self.Modified()

    @smproperty.stringvector(name="SeriesLineStyle", element_types="2 0", number_of_elements_per_command=2, repeat_command=1)
    @smdomain.xml("""<ChartSeriesSelectionDomain name="array_list" default_mode="value" default_value="1" hide_partial_arrays="0">
                        <RequiredProperties>
                            <Property function="Input" name="Input" />
                            <Property function="FieldDataSelection" name="AttributeType" />
                            <Property function="CompositeIndexSelection" name="CompositeDataSetIndex" />
                        </RequiredProperties>
                    </ChartSeriesSelectionDomain>""")
    def iSetLineStyle(self,name):
        self.Modified()

    @smproperty.stringvector(name="SeriesLineThickness", element_types="str int", number_of_elements_per_command=2, repeat_command=1)
    @smdomain.xml("""<ChartSeriesSelectionDomain name="array_list" default_mode="value" default_value="2" hide_partial_arrays="0">
                        <RequiredProperties>
                            <Property function="Input" name="Input" />
                            <Property function="FieldDataSelection" name="AttributeType" />
                            <Property function="CompositeIndexSelection" name="CompositeDataSetIndex" />
                        </RequiredProperties>
                    </ChartSeriesSelectionDomain>""")
    def jSetLineThickness(self,name):
        self.Modified()

    @smproperty.stringvector(name="SeriesMarkerStyle", element_types="2 0", number_of_elements_per_command=2, repeat_command=1)
    @smdomain.xml("""<ChartSeriesSelectionDomain name="array_list" default_mode="value" default_value="0" hide_partial_arrays="0">
                        <RequiredProperties>
                            <Property function="Input" name="Input" />
                            <Property function="FieldDataSelection" name="AttributeType" />
                            <Property function="CompositeIndexSelection" name="CompositeDataSetIndex" />
                        </RequiredProperties>
                    </ChartSeriesSelectionDomain>""")
    def kSetMarkerStyle(self, name):
        self.Modified()

    @smproperty.stringvector(name="SeriesMarkerSize", element_types="str double", number_of_elements_per_command=2, repeat_command=1)
    @smdomain.xml("""<ChartSeriesSelectionDomain name="array_list" hide_partial_arrays="0" default_mode="value" default_value="4">                      
                        <RequiredProperties>
                            <Property function="Input" name="Input" />
                            <Property function="FieldDataSelection" name="AttributeType" />
                            <Property function="CompositeIndexSelection" name="CompositeDataSetIndex" />
                        </RequiredProperties>
                    </ChartSeriesSelectionDomain>""")
    def lSetMarkerSize(self, name):
        self.Modified()
        
    @smproperty.doublevector(name="Color", default_values=[1.0, 0.0, 1.0], number_of_elements=3, panel_visibility="never")
    @smdomain.xml("""<DoubleRangeDomain max="1 1 1" min="0 0 0" name="range" />
                    <Hints>
                        <PropertyLink group="settings" proxy="ColorPalette" property="SelectionColor" unlink_if_modified="1" />
                    </Hints>""")
    def mSetSelectionColor(self, name, name2, name3):
        self.Modified()

    @smproperty.stringvector(name="SeriesLabelPrefix", number_of_elements=1, default_value=" ", panel_visibility="advanced")
    def nSetSeriesLabelPrefix(self, name):
        self.Modified()

    @smproperty.stringvector(name="LastPresetName", number_of_elements=1, default_values="Spectrum", panel_visibility="never")
    def oSetLastPresetName(self, name):
        self.Modified()

    @smproperty.xml(xmlstr="""<PropertyGroup label="Series Parameters" panel_widget="SeriesEditor" panel_visibility="default">
                                <Property name="SeriesVisibility" function="SeriesVisibility"/>
                                <Property name="SeriesColor" function="SeriesColor"/>
                                <Property name="SeriesLineThickness" function="SeriesLineThickness"/>
                                <Property name="SeriesLineStyle" function="SeriesLineStyle"/>
                                <Property name="SeriesLabel" function="SeriesLabel"/>
                                <Property name="SeriesMarkerSize" function="SeriesMarkerSize"/>
                                <Property name="SeriesMarkerStyle" function="SeriesMarkerStyle"/>
                                <Property name="SeriesPlotCorner" function="SeriesPlotCorner"/>
                                <Property name="LastPresetName" function="LastPresetName"/>
                            </PropertyGroup>
                            <Hints>
                                <InitializationHelper class="vtkSMXYChartRepresentationInitializationHelper"/>
                            </Hints>""")
    def pGroupSeriesParameters(self,name):
        self.Modified()