GUI - Import/Export - Automation

<< Click to Display Table of Contents >>

Navigation:  PipeLay > Software Introduction > GUI Basics > GUI - Import/Export Functionality >

GUI - Import/Export - Automation

Previous page Next page

The Plain Text or XML file of the exported model can be parsed and modified as required to generate a new model configuration to facilitate easy automation of a large number of analyses. To illustrate this, the Extensible Mark-up Language (XML) format has been used as its structure is easily read.

The Python programming language (V2.7) was used to create an example script. The script exports Standard Example 15 - Shallow Water Rigid S-Lay to XML to use as a base model for modification as the Python package ElementTree allows for easy reading, storage and manipulation of the XML information tree. A series of new stinger configurations have been calculated and stored externally in a spreadsheet which are read using the external package openpyxl which is a Python library for reading and writing Excel 2010 xlsx files. The script loads the base model XML and cycles over the XML tree to find and modify the support locations and generate new model configurations. Once all the XML models for the new stinger configurations have been created, they are imported back into PipeLay project files (*.ppd) and the analyses are executed via command line calls.

Information and links for the download and installation of Python and the associated packages used in the script are detailed in the next section entitled ‘Python’.

The verbatim Python code is given below and is also available in the Example 15 – Shallow Water Rigid S-Lay directory as a Python script entitled EX15-Python-Automation-Script.py.

The code comments indicated by the # symbol outline the basic operation of the script:

 

# Python Script for PipeLay Import/Export automation. 
# The following steps are carried out:
#
# Libraries used for parsing the xml tree, accessing Excel data and 
# general purpose are imported.
#
# The PipeLay model for Example 15 - Shallow Water Rigid S-Lay is
# exported to xml format to serve as a base model for modification.
#
# An Excel workbook containing calculated stinger support data providing
# new stinger configurations is loaded.
#
# The Example 15 base xml model is parsed and cycled over to find X & Y 
# support locations and support data is updated with data in spreadsheet.
# The Analysis component is renamed to reflect new stinger configuration.
#
# A new xml model file is created for updated stinger configuration and 
# stored in a new directory.
#
# The new xml stinger models are imported into PipeLay project ppd files and
# the analyses are executed
from openpyxl import load_workbook
import xml.etree.ElementTree as ET
import os, subprocess, io, inspect
import shutil
 
# Get the current working directory
cwd = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
 
# Set path to current PipeLay installation (Must equal or greater than V3.4.1 for this script)
pipelay_exe = r"C:\Program Files\Wood Group\PipeLay v3.4.1\bin\pplstd.exe"
example_15 = r"Example 15 - Shallow Water Rigid S-Lay.ppd"
 
args = [' '] * 3 # Command line argument list
                 # args[0] = PipeLay Executable
                 # args[1] = PipeLay Project file (.ppd) or XML/txt to import
                 # args[2] = Additional arguments:
                 # /SAVEAS - save as a specific file name. Defaults to .ppd name if not present
                 # Analysis Command line options: /RUNTYPE 
                                               #  /FULL - Run a full analysis.
                                               #  /POS  - Run postprocessing only
                                               #  /SUM  - Run summary postprocessing only
                                               #  /DNV  - Run code checking DNV postprocessing only
                                               #  /API  - Run code checking API postprocessing only
                                               #  /HIS  - Run time history
                                               #  /FAT  - Run fatigue postprocessing
                                               #  /TAB  - Run tabular postprocessing only
 
args[0] = pipelay_exe # Add the PipeLay executable to the command line argument list
 
# Setup export of PipeLay EX15 *.ppd file command line arguments
args[1] = cwd + "\\" + example_15
args[2] = "/EXPORT=XML"
 
# Export EX15 model to xml 
subprocess.call(args)
 
# Load the stinger data spreadsheet
xlwb = load_workbook(cwd + "\\stinger_config_data.xlsx")
sheet = xlwb.get_sheet_by_name('Data')
 
# Initalise data variables
num_models     = int(sheet['A1'].value) # Number of Stinger Configurations  
start_row      = int(sheet['A2'].value) # Starting Row
start_col      = int(sheet['A3'].value) # Starting Column
column_spacing = int(sheet['A4'].value) # Column increment
x_row          = start_row              # Starting row for x data
y_row          = start_row              #    "      "   "  y  "
x_col          = start_col              #    "   column "  x  "
y_col          = start_col + 1          #    "   column "  y  "
analysis_stub = 'Stinger-'
 
# Initialise list array for storing model names and paths 
model_name_paths = [[' ' for i in range(3)] for j in range(num_models)] 
 
# Parse the EX15 xml tree
tree = ET.parse(cwd + "\\" +example_15[:-3] + "xml")
root = tree.getroot()
 
# Cycle over the different stinger configurations
for istinger in range(num_models):
    # Cycle over the tree searching for Support X & Y locations
    for slot in root.iter('Slot'):
        slotname = slot.attrib.get('name')
        if slotname == 'Support Location - X':
            # Replace current support location value with new data from spreadsheet 
            slot.attrib['value'] = str(sheet.cell(row=x_row,column=x_col).value)
            x_row = x_row + 1
        elif slotname == 'Support Location - Y':
            # Replace current support location value with new data from spreadsheet
            slot.attrib['value'] = str(sheet.cell(row=y_row,column=y_col).value)
            y_row = y_row + 1
        elif slotname == 'Support Location - Angle':
            slot.attrib['value'] = ""
    # Cycle over the tree searching for the Analysis component and rename 
    for component in root.iter('Component'):
        component_type = component.attrib.get('type')
        if component_type == 'Analysis':
            # Rename the analysis component
            analysis_name = 'Normal Lay Analysis-' + analysis_stub + str(istinger + 1
            component.attrib['name'] = analysis_name
    
    # Store analysis name
    model_name_paths[istinger][0] = analysis_name
 
    # Write the output filename
    file_out = example_15[:-4] + '-' + analysis_stub + str(istinger + 1) + '.xml'
 
    # Make new analysis directory
    dir_out = file_out[:-4]
    new_dir_path = cwd + '\\' + dir_out
    model_name_paths[istinger][1] = new_dir_path
 
    if not os.path.exists(new_dir_path):
        os.makedirs(new_dir_path)

 

    for file in os.listdir(cwd):

        if file.endswith(".rao"):

            try:

                shutil.copy(file, new_dir_path)

            except IOError as e:

                print("Unable to copy RAO file. %s" % e)

            except:

                print("Unexpected error:", sys.exc_info())

 
    # Append full model path and store for later    
    path_to_model = new_dir_path + '\\' + file_out
    model_name_paths[istinger][2] = path_to_model
 
    # Write the new xml file
    tree.write(path_to_model)
    x_row = start_row
    y_row = start_row
    x_col = x_col + column_spacing
    y_col = y_col + column_spacing
 
 
for ianalysis in range(num_models):
    # Create import command line string
    args[1] = "/IMPORT=" + model_name_paths[ianalysis][2
    args[2] = ""
 
    # Call PipeLay to import and convert model to .ppd
    subprocess.call(args)
 
    # Create run analysis command line string
    ppd_file = model_name_paths[ianalysis][2]
    args[1] = ppd_file[:-3] + "ppd"
    args[2] = "/RUNTYPE=" + model_name_paths[ianalysis][0]
 
    # Call PipeLay to run analysis
    subprocess.call(args)
 
    # Output progress from PipeLay batchlog file
    print('Analysis: ' + args[1] + '\n'
    log_file = model_name_paths[ianalysis][1] + "\\batchlog.txt"
    if os.path.isfile(log_file):
        with open(log_file) as lf:
            print(list(lf))[-1]
        lf.close()
    else:
        print "No analysis output"