Ask Your Question

Revision history [back]

Old post I know, but for anyone else chasing this like I was: setdiagresvrcs () and a few other sld settings-related functions have a keyword 'scope' which determines whether to edit settings for active, global (i.e. default) or both. From what I've found there are a handful of settings that will need to be done manually no matter what, but these are generally global settings or context dependent (like animating flows) so despite the frustration you will get a habit for which ones are the common culprits.

I've made a script for changing what require the most fiddling. As stated in the module description it's written to be loaded directly into PSSE, or drag and drop while having the active SLD open. The global parameter SCOPE = 2 will change only the active sld by default. This is still a personal WIP- see comments for things that aren't working yet or contradict the API based on testing.

Godspeed.

"""
This script was written for PSSE v34.5.1 in Python 2.7.18
Drag and drop into the PSSE GUI to run, ideally with an active SLD,
Although you can load using the TEST_SLD_FILE variable.
! IMPORTANT:
!   These functions behave strangely and the API is *INCORRECT* in several
!   areas.
!   For some reason the default values (_i, _f, _s) do not work for
!   these sld functions for some keywords.
! Make sure to set Diagram Items are NOT bound in Edit-> Preferences

This version is customized to be specifically for printing.
NOTE: If you wish to include animated flows and current loadings
    they must first be enabled in the active case!

GLOBAL Arguments:
    SCOPE {int} --
        0: default settings only
        1: default settings and active sld
        2: active sld only
    TEST_SLD_FILE {str} --
        Mainly for debugging. NOTE: do not include '.sld'
"""

SCOPE = 2
TEST_SLD_FILE = None
# ENTER sld path\\name to test - only for debugging
# TEST_SLD_FILE = "C:\\your project\\your beautiful sld""


def voltage_thresholds(scope=2):
    """
    Enabling voltage thresholds in Slider Diagrams. Default settings
        match NEM SLD colours (exception: 500 kV. Because yellow on
        white should be illegal)

    v_th {dict} -- [kV, rgb(0,0,0), linewidth]
    'V0': [0.00,  (1, 1, 1), 1] is not a specific voltage,
        it serves as the colour for below minimum defined in V1
    """

    v_th = {
        'V0': [0.00,  (230, 1, 1), 1],
        'V1': [11.0,  (1, 1, 1), 1],
        'V2': [33.0,  (119, 65, 16), 1],
        'V3': [66.0,  (192, 2, 45), 1],
        'V4': [132.0, (0, 0, 255), 2],
        'V5': [220.0, (229, 0, 126), 2],
        'V6': [275.0, (242, 170, 45), 3],
        'V7': [330.0, (0, 255, 255), 3]
    }
    v_ranges = [v[0] for v in v_th.values()]
    v_ranges.remove(0.00)  # drop as it is not part of the range
    rgb_red = [rgb[1][0] for rgb in v_th.values()]
    rgb_green = [rgb[1][1] for rgb in v_th.values()]
    rgb_blue = [rgb[1][2] for rgb in v_th.values()]
    linewidths = [w[2] for w in v_th.values()]

    psspy.setdiagresvrcs_2(
        setscope=scope,
        usevolt=1,
        vlnwdt=linewidths,
        vltval=v_ranges,
        vlnclrr=rgb_red,
        vlnclrg=rgb_green,
        vlnclrb=rgb_blue,
        useoosclr=1,
        usevoltlay=1
    )

    return


def power_flow_settings(scope=2):
    """
    settings for power flow, displaying pu/kV and
    setting line ratings to normal/emer.

    setdiagprec() is best left hard-coded. Change scope=2 if not working
        default code below sets pu values to 3 decimal places
    psspy.setdiagprec_2(
        setscop -- NOTE: TYPO in API!
        diagprec -- decimal places. NOTE: last 4 entries should be 0!
        )

    setdiagrespflowoptions_3 is also a mess, will usually call twice
        when manually recording in PSSE. e.g.:
            psspy.setdiagrespflowoptions_3(
                2, _i, _i, _i, _i, _i, _i, _i, 1, 2, 1, 1)
            psspy.setdiagrespflowoptions_3(
                2, 0, 0, 4, 0, 1, 0, 0, _i, _i, _i, _i)
    ! FLWOPT in API is wrong!
        flwopt: 0=signs, 1=arrows
    ! BUSIDANN, BRNIDANN, EQIPIDANN descriptions in API are wrong!
        busidann: 0=number/no name, 1=name/no number, 2=both, 3=none
        brnidann: 0=No ID, 1=ID
        eqipidann: 0=No ID, 1=ID

    setdiagrespflowcheck_3() Used to specify the Power Flow voltage and
        range checking annotation options.
    ! DESPITE What the api says, set BRNRAT as so:
        brnrat: 1=continuous, 2=emer rating
    ! Overload and flow animations must be manually enabled in
    !    Active SLD in order for them to appear in print!

    setdiagresdata_3() don't really know what this does tbh.
        Values in manual recording don't match API accepted values.
    """

    psspy.setdiagprec_2(
        scope,
        [2, 2, 2, 3, 0, 0, 0, 0]
    )

    # 'flow':   0 for MW/MVAR, 1=MVA, 2=%MVA/rating, 6 for none
    #           NOTE: Apparently 9=None?
    # 'busvlt': 0=pu, 1=kV, 2=angle 3=pu+angle,
    #           7=pu+angle+kV, 8=None
    #           (see other options in API)
    #           NOTE: This will change what is shown next to buses!
    # 'equip': Will change machine labels.
    equipment_options = {
        'flow': 1,
        'flowopt': 0,
        'busvlt': 8,
        'equip': 0
    }

    id_options = {
        'bus': 1,
        'branch': 0,
        'equip': 0
    }
    loading = 1  # 0=current, 1=MVA

    psspy.setdiagrespflowoptions_3(
        setscope=scope,
        brnann=equipment_options['flow'],
        busvlt=equipment_options['busvlt'],
        eqipann=equipment_options['equip'],
        pmvaline=loading,
        busidann=id_options['bus'],
        brnidann=id_options['branch'],
        eqipidann=id_options['equip']
    )

    # (Shows overload graphically)
    # logarr = [line ratings, bus voltage]. Bool
    #           95% loading to capture thermal limits are close
    # llodarr = line size and "style" when overloaded
    #           NOTE: DESPITE What the api says, BRNRAT should be:
    #           brnrat: 1=continuous, 2=emer rating (RATE A, RATE B)
    psspy.setdiagrespflowcheck_3(
        setscope=scope,
        logarr=[1, 0],
        linlod=95.0,
        llodarr=[7, -1],
        llodclr=[204, 0, 204],
        brnrat=1,
        barpercent=[95, 100, 105, 110],
        barclrr=[204, 255, 204, 128],
        barclrg=[0, 0, 0, 0],
        barclrb=[204, 0, 0, 0]
    )

    # Use this API to specify the basic Power Flow annotation options
    # in the active Slider Diagram. At least that is what the API thinks
    psspy.setdiagresdata_3(
        setscope=scope,
        brnann=9,               # 6=impedances, 7=ratings, 9=nothing
        busann=0,               # 0=no base kV, 1=base kV
    )

    return


def diagram_display_settings(scope=2):
    """
    NOTE: Does not record in psse automation when manually changing
        settings!
    ! grid style settings grdstyl, grdptrn appear to be broken!

    psetdiagprop_5(
        setscope  -- scope of settings (default: {1})
        bkgclr    -- background colour (default: [255, 255, 255])
        grdclr    -- grid colour = light grey [192, 192, 192]
        uparwclr  -- active power flow arrows (default: [0, 128, 0])
        dwnarwclr -- reactive power flow arrows (default: [255, 128, 0])
        labclr    -- bus labels (default: [0, 0, 0])
    !   # grdstyl -- grid style: 0=dotted, 1=lined. BROKEN!
    !   # grdptrn -- (int) Broken!
        fltval1   -- grid point size
        fltval2   -- default line width in pixels?
        dblval9   -- grid spacing
        dblval10  -- grid snap distance
        dblval11  -- branch spacing?
    )
    """

    psspy.setdiagprop_5(
        setscope=scope,
        bkgclr=[255, 255, 255],
        # prtclr=[0,0,0],
        grdclr=[255, 255, 255],
        uparwclr=[0, 128, 0],
        dwnarwclr=[255, 128, 0],
        labclr=[0, 0, 0],
        # grdstyl=1,
        # grdptrn=0,
        fltval1=0.5,
        fltval2=1.0,
        dblval9=0.25,
        dblval10=0.25,
        dblval11=0.5,
    )

    return


def print_sld():
    psspy.printdiagfile(
            sdev=r"""Microsoft Print to PDF""",
            copies=1,
            orient=2
            )

    # Comment out if you want to debug the SLD formatting
    # psspy.closediagfile()

    return

if __name__ == "__main__":

    if TEST_SLD_FILE is not None:
        psspy.opendiagfile("{}.sld".format(TEST_SLD_FILE))

    # Comment out sld functions as required.
    voltage_thresholds(SCOPE)
    power_flow_settings(SCOPE)
    diagram_display_settings(SCOPE)


    if TEST_SLD_FILE is not None:
        psspy.savediagfile("{}_updated.sld".format(TEST_SLD_FILE))

    # Uncomment to print to PDF
    # print_sld()