An interactive method for converting SWMM model data into data directly recognized by a graph neural network

By converting SWMM model data into a format recognizable by graph neural networks, the problem of low data processing and analysis efficiency is solved, enabling efficient urban drainage system design and management, and providing more accurate flood risk assessment and planning support.

CN119720756BActive Publication Date: 2026-03-31CHONGQING JIAOTONG UNIV
View PDF 2 Cites 0 Cited by

Patent Information

Authority / Receiving Office
CN · China
Patent Type
Patents(China)
Current Assignee / Owner
Filing Date
2024-12-04
Publication Date
2026-03-31

AI Technical Summary

Technical Problem

The output data of existing SWMM models are difficult to directly apply to advanced machine learning and artificial intelligence technologies such as graph neural networks. Especially when dealing with large-scale datasets, they cannot effectively integrate the physical and hydrological attributes of nodes and edges into the graph structure, resulting in low data processing and analysis efficiency and failing to provide accurate and real-time support for urban hydrological management.

Method used

The node and pipe data of the SWMM model are extracted and normalized using MATLAB software, and then visualized using Python. The data is converted into a format that can be recognized by graph neural networks, including node feature matrices and pipe connection relationships. Isolated nodes are removed to achieve a concise and intuitive representation of the data, which facilitates graph neural network analysis of urban drainage problems.

Benefits of technology

It improves data availability and analysis efficiency, helps identify potential problems in drainage systems, predicts water level changes and flood susceptibility, reduces human error, improves system response speed and disaster management capabilities, and supports urban flood risk assessment and planning optimization.

✦ Generated by Eureka AI based on patent content.

Smart Images

  • Figure CN119720756B_ABST
    Figure CN119720756B_ABST
Patent Text Reader

Abstract

The application discloses an interactive method for converting SWMM model data into data directly recognized by a graph neural network, and comprises the following steps: first, based on MATLAB software, an.inp file of the SWMM model is read and information is extracted, pipe connection relationship information is saved as a first npy file, pipe length information is saved as a second npy file, then the catchment area, maximum impervious rate, total width, maximum slope, whether a discharge outlet, node elevation and node depth data associated with each node are extracted and normalized to obtain a node feature matrix which is saved as a third npy file. In the second step, the npy file is visualized by using python software. The application simplifies the data processing process, realizes the rapid structuring of the SWMM model data, and provides accurate and real-time analysis support for urban hydrological management.
Need to check novelty before this filing date? Find Prior Art

Description

Technical Field

[0001] This invention belongs to the field of urban stormwater simulation data processing technology, specifically relating to an interactive method for converting SWMM model data into data that can be directly recognized by graph neural networks. Background Technology

[0002] In the process of urbanization, urban drainage systems and stormwater management are important components of urban infrastructure planning and environmental protection. With the expansion of urban areas and the increase in impermeable surfaces, the risk of urban flooding disasters has significantly increased. Effective urban stormwater management requires not only accurate data collection and monitoring, but also efficient data processing and analysis methods to predict and regulate flood events.

[0003] Urban stormwater management models (SWMMs) are comprehensive computer models used to simulate individual stormwater events or continuously simulate runoff and water quality in urban areas. SWMMs can simulate rainfall-runoff processes in both natural and man-made areas, calculating the transformation from rainfall volume to the amount discharged into receiving water bodies. They are one of the standard tools for the design and analysis of urban drainage systems. However, the data output by SWMMs is often complex and in unstructured formats, such as nodal flow rates, water levels, and pipe network connections. This data typically only reflects the rainfall process and the performance of the urban drainage system itself and related aspects, but it cannot reflect the performance and problems in the design, construction, operation, and management of drainage system facilities, nor can it be analyzed at these levels. Therefore, further conversion and processing are required to make it suitable for more advanced data analysis methods.

[0004] While SWMM demonstrates excellent simulation accuracy, its data processing and analysis capabilities are relatively limited, especially when dealing with large-scale datasets. This makes it difficult to directly apply to advanced machine learning and artificial intelligence techniques, such as graph neural networks. Graph Neural Networks (GNNs) have proven excellent at analyzing data with complex network structures, particularly when the relationships between nodes and edges are crucial to the overall analysis. However, transforming SWMM output data into a format directly usable by graph neural networks presents certain technical challenges. For example, how to effectively integrate the physical and hydrological properties of nodes and edges into the graph structure, and how to process and represent this data to optimize neural network performance.

[0005] Given the limitations of existing technologies, there is a need to develop a method that can efficiently transform SWMM output data and adapt it to graph neural networks. This method can not only improve data availability and analysis efficiency, but also leverage the powerful data processing capabilities of graph neural networks to provide more accurate and real-time decision support for urban hydrological management. Summary of the Invention

[0006] To address the shortcomings of the existing technologies, the technical problem this invention aims to solve is: how to provide an interactive method that can improve data availability and analysis efficiency by converting SWMM model data into data that can be directly recognized by graph neural networks, enabling the use of the powerful data processing capabilities of graph neural networks for overall analysis, facilitating various studies related to urban precipitation, and providing more accurate and real-time decision support for urban hydrological management.

[0007] To solve the above-mentioned technical problems, the present invention adopts the following technical solution:

[0008] An interactive method for converting SWMM model data into data that can be directly recognized by graph neural networks, first establishing an SWMM model of the urban area under study, dividing the watershed into zones, and exporting an .inp (text file with the .inp extension) file; characterized by further including the following steps:

[0009] Step 1: First, using MATLAB (a commercial mathematical software for data analysis), the .inp file of the SWMM model is read. The X-axis and Y-axis coordinates of each node are extracted and normalized. Then, the pipe connection relationships (i.e., information about the pipes and their two ends) and pipe length information are extracted. After extraction, the pipe connection relationship information is saved as the first .npy file (a binary file used to store array data), and the pipe length information is saved as the second .npy file. Next, the catchment area, maximum impermeability, total width, maximum slope, whether it is a discharge outlet, node elevation, and node depth data associated with each node are extracted and normalized. Finally, the node X and Y positions, catchment area, maximum impermeability, total width, maximum slope, whether it is a discharge outlet, node elevation, and node depth data are integrated and saved as a node feature matrix, which is then saved as the third .npy file.

[0010] Step 2: Use Python (a computer language) to perform visualization processing based on the three .npy files.

[0011] Thus, in this invention, the node-related data, pipe connection relationships, and pipe length data are first normalized and saved as three different .npy files. This step transforms all data from the SWMM model's .inp file into a form that graph neural networks can directly recognize and use. Graph neural networks can help identify potential drainage problems in the area (such as waterlogging, sewage overflow, etc.), and can also help understand the flow process of water in the drainage system, predict future water level changes, and the susceptibility to urban flooding, thus better assisting researchers in assessing urban flood risks. Then, based on these three .npy files, visualization is implemented using Python software. In this step, isolated nodes (nodes without pipe connections to other nodes) are processed... The data has been processed to remove unnecessary information, transforming complex data into simpler and more intuitive graphics. This helps users quickly identify key nodes and pipes in the model, as well as the relationships and interactions between them. This process also makes it easier for users to identify nodes lacking catchment areas and outlets, aiding in decision-making optimization. For example, in urban flood risk assessments, it allows for a rapid understanding of the relative positions of various nodes in the urban drainage system and the direction of water flow. This enables designers to more intuitively add pipes to flood-prone areas and adjust nodes lacking catchment areas. Furthermore, it allows urban planners to better plan and adjust urban functional zones or emergency measures in flood-prone areas.

[0012] Therefore, this invention enables direct interaction between the SWMM model and Python's graph neural network using MATLAB software, facilitating the direct analysis of various urban flooding data and related research using graph neural network algorithms. By combining SWMM and GNN, higher levels of automation and intelligence can be achieved in the design, optimization, and operation management of urban drainage systems, effectively reducing human error and improving system response speed and disaster management capabilities.

[0013] In this scheme, a node refers to a connection point of the pipelines in the urban drainage network system. The connection point can be a diverter, storage unit, or outlet. These nodes play a key role in the network structure of the drainage system. They connect different links (such as pipes, channels, etc.) and allow water to flow or be stored between these links.

[0014] In this scheme, the X-axis and Y-axis coordinates of each node refer to the geometric coordinates of the node in two-dimensional space, used to describe its specific location in the drainage network within the model. The X and Y positions of the nodes are stored in node_positionX (variable matrix name) and node_positionY, respectively, and are normalized to generate node_positionX_norm and node_positionY_norm.

[0015] In this scheme, the catchment area associated with each node refers to the sum of the catchment areas of all regions converging at a node, representing the range of rainwater sources received by that node. In the model, the catchment area directly affects the input water volume of a node and is one of the key determinants of node flow rate. A larger catchment area means that the node needs to handle a larger volume of rainwater, potentially putting higher pressure on downstream pipelines. The catchment area is represented by the variable `mjjz` in the initial step and is then subjected to min-max normalization in subsequent processing to generate the normalized result `mjjz_norm`.

[0016] In this scheme, the maximum imperviousness associated with each node refers to the proportion of impervious surfaces (such as buildings, roads, etc.) within the catchment area associated with a node to the total area. It reflects the portion of rainwater runoff that cannot permeate into the ground within the node's catchment area. A higher maximum imperviousness at a node results in a larger volume of surface runoff collected, increasing the burden on downstream pipe networks. In the steps, this physical quantity is stored as the variable `imperviousness_doub` and normalized to generate `imperviousness_norm`.

[0017] In this scheme, the total width associated with each node (Subcatchment Width) refers to the total width of the water flow path within the catchment area associated with a node, describing the degree of dispersion of water flow converging at the node. A larger total width indicates a shorter water flow path and a faster water flow velocity, thus potentially resulting in a greater water flow impact received by the node. This physical quantity is represented by the variable subWidth_doub in the steps, and the normalized result is stored as subWidth_norm.

[0018] In this scheme, the maximum slope associated with each node refers to the maximum topographic slope of the catchment area associated with a node, representing the acceleration capacity of the water flow within the area. A larger slope results in faster water flow to the node, potentially causing greater flow pressure on the node. A smaller slope leads to slower water flow and longer convergence time. This physical quantity is represented by slope_doub and normalized to generate slope_norm.

[0019] In the scheme, the outlet (Is Outlet) associated with each node indicates whether a node is the final discharge point of the drainage system. It is stored as a Boolean value, with 0 representing a normal node and 1 representing an outlet node. Outlet nodes are critical points in the entire drainage system, directly affecting drainage efficiency. For outlet nodes, water is discharged from the system to the external environment; non-outlet nodes are merely nodes for water flow transmission within the pipe network. In the steps, this attribute is stored in the fifth column of the matrix X_combine to identify the function of the node.

[0020] In this scheme, the node elevation associated with each node refers to the ground height of a node, reflecting the terrain features at the node's location. Elevation affects the gravity flow direction of water and is a key parameter determining whether water can be discharged smoothly. Elevation data is stored as Node_bottomElevation and normalized to generate Node_bottomElevation_norm for subsequent model calculations.

[0021] In this scheme, the node depth associated with each node refers to the maximum depth from the ground of that node to the bottom of the drainage pipe. It represents the node's maximum water capacity; the greater the depth, the more water the node can hold. Node depth is stored as Node_MaxDepth and normalized to generate Node_MaxDepth_norm.

[0022] The first step of this method specifically includes the following steps:

[0023] Step 1: Open the SWMM model using MATLAB software and extract the information data from the inp file; convert all data content into a variable matrix newline (variable matrix name) for subsequent processing.

[0024] The specific implementation process of step 1 is as follows:

[0025] 1) Set the simulation step size: Define a variable time_step with a value of 5, which means that the simulation is performed once every 5 minutes.

[0026] 2) Clean up the environment: Use the clear and clc commands to clear variables and command windows in the MATLAB environment to prepare for new file operations.

[0027] 3) File path and mode: Open a .inp file containing SWMM model data using the fopen (open file and set read / write mode command) function. The file is opened in read / write mode (r+) to allow modification of the file content.

[0028] 4) Initialize variables: Initialize variable i and array newline. newline is used to store each line of data read from the file.

[0029] 5) Loop reading: Use a while loop and the feof function to check if the file has reached the end. This loop remains active until the file has been completely read.

[0030] 6) Read line by line: Use the fgetl (command to read file content line by line) function to read the file content line by line. After each line is read, the variable i is incremented by 1, and the read line is stored in the newline array.

[0031] 7) Close file operations: Use the `fclose(fileID)` command to close previously opened files. This is an important operation used to release system resources and ensure that all changes are saved.

[0032] Step 2: Extract the X and Y coordinate information of the nodes. That is, extract the node name and coordinate information from the variable matrix newline in Step 1, and convert it into a node number and name matrix node_name, node position X coordinate node_positionX, and node position Y coordinate node_positionY, so as to be used for the establishment of the graph structure.

[0033] Step 2, when implemented, includes the following operational steps:

[0034] 1) Initialize and find node positions: Use the `contains` function (command to check if a string array contains a specific substring) and the `find` function (command to find the index of an element that meets a certain condition) to find and locate the rows in the `newline` array that contain 'COORDINATES' (i.e., the row with the coordinates) and 'VERTICES', and store them in the variables `node_id` and `node_idend`, respectively. By finding the positions of these keywords, the start (3 rows below the row containing 'COORDINATES') and end (1 row above the row containing 'VERTICES') of the node data can be located.

[0035] 2) Calculate the number of nodes: Based on the start and end positions of the node data, calculate the total number of nodes. This is obtained by subtracting the start position plus one from the end position and storing it in the variable num_node.

[0036] 3) Loop to extract node data: Use a for loop to extract data from each node, starting from the beginning and according to the number of nodes.

[0037] 4) Data splitting using expressions: Use the regexp (a command to split strings using regular expressions) function and the expression \s+ to split each line of data. This allows you to extract node names and coordinate information. This expression splits the string based on spaces to obtain detailed node information.

[0038] 5) Store node information: Store the node number and name, the X-axis coordinate of the node position, and the Y-axis coordinate of the node position into the predefined variables node_name, node_positionX, and node_positionY, respectively.

[0039] Step 3: Normalize the X and Y coordinate data of the nodes. That is, convert the node X and Y coordinate information extracted in Step 2 into normalized values ​​and store them in the matrices node_positionX_norm and node_positionY_norm respectively to ensure that the data is within the range of 0 to 1.

[0040] Step 3, when implemented, includes the following operational steps:

[0041] 1) String to number conversion: Use the str2double (command to convert string to double) function to convert the node coordinates node_positionX and node_positionY from string format to double floating-point numbers.

[0042] 2) Use min-max normalization to process the coordinate data: Calculate the minimum and maximum values ​​of node_positionX and node_positionY respectively. These values ​​are used in the subsequent normalization process to ensure that all coordinates are scaled to the range between 0 and 1.

[0043] 3) Perform normalization: Normalize node_positionX and node_positionY by using a normalization formula to convert each coordinate value into a value in the range of 0 to 1, where the minimum coordinate becomes 0 and the maximum coordinate becomes 1. After calculation, store the data in the variables node_positionX_norm and node_positionY_norm respectively.

[0044] The normalization process is explained here:

[0045] Normalization is typically a process of scaling data values ​​of different features to a relatively consistent range to facilitate model processing or further data analysis.

[0046] The first step in the normalization process is to determine the minimum and maximum values. For data that needs to be normalized (such as the X and Y coordinates of a node, or the length of a pipe), the minimum and maximum values ​​of these data need to be calculated first.

[0047] Minimum value: Use the min() function to find the minimum value in the data.

[0048] Maximum value: Use the max() function to find the maximum value in the data.

[0049] The second step is to use the normalization formula, which is:

[0050]

[0051] In this formula:

[0052] original_value: This is the original data value, such as the original coordinates of a node or the original length of a pipe.

[0053] min_value: is the minimum value calculated in the first step.

[0054] max_value: is the maximum value calculated in the first step.

[0055] normalized_value: The normalized value, which usually falls within the range of [0,1].

[0056] Normalizing data ensures that all features are within the same magnitude range, which is crucial for subsequent data modeling and analysis. In particular, in graph neural network models, normalization can prevent certain feature values ​​from having an unbalanced impact on model training due to excessively large scales.

[0057] Through this normalization process, all data are scaled to the same interval [0,1], which facilitates subsequent model training or data visualization.

[0058] Step 4: Extract pipeline information from the variable matrix newline in Step 1, including the pipeline and its two end connection nodes and their lengths, and store them in the matrices link_name, graph_connection1 (starting end), graph_connection2 (ending end), and link_length.

[0059] Step 4 specifically includes the following operational procedures:

[0060] 1) Find the key identifier: Use the `contains` and `find` functions to search the `newline` array for lines containing 'CONDUITS' (i.e., the lines containing pipeline data connecting two nodes). This marks the beginning of the pipeline data and is stored in the variable `link_id`. Use the `find` function to determine the position of this line and adjust the offset to determine the actual starting line of the data (i.e., the three lines below the line containing 'CONDUITS'), and store it in the variable `link_id_position`.

[0061] 2) Determine the end position of the data: Use the `contains` and `find` functions to locate the row containing 'XSECTIONS' and store it in the variable `link_idend`. This marks the end of the pipeline data. Adjust the offset to determine the actual end row of the data (i.e., the two rows above the row containing 'XSECTIONS') and store it in the variable `link_idend_position`.

[0062] 3) Calculate the number of pipes: Use the start and end positions to calculate (i.e., subtract link_id_position from link_id_position plus one) to get the total number of pipes.

[0063] 4) Loop through pipeline data: Use a for loop to iterate from the first pipeline data row to the last pipeline data row.

[0064] 5) Regular expression splitting of data: Split each line using the regexp function and \s + regular expression. This regular expression uses one or more spaces as delimiters to extract the pipe name and related connection nodes and length.

[0065] 6) Store the extracted pipeline data: The name of the extracted pipeline, the names of the two end connection nodes, and the length of the pipeline are stored in link_name, graph_connection1 (starting end), graph_connection2 (ending end), and link_length, respectively.

[0066] Step 5: Establish the pipeline connection matrix edges to store the starting and ending node index positions of each pipeline, so as to be used for connection relationship modeling in graph neural networks.

[0067] Step 5 specifically includes the following operational procedures:

[0068] 1) Edge Matrix Definition: Initialize a matrix of size num_link x 2 named edges using the zeros function (command to create an array of all zeros). This matrix stores the indices of the start and end nodes of each pipeline in the graph. Each row represents a pipeline, with the first column storing the index of the start node and the second column storing the index of the end node.

[0069] 2) Loop through the pipe data: Use a for loop, with variable i as a counter (i.e., which pipe), and traverse from the first pipe to the last pipe.

[0070] 3) Extract node names: Inside the loop, retrieve the names of the start node (startNode) and end node (endNode) of the current (i.e., the i-th) pipeline from the previously created graph_connection1 and graph_connection2 arrays.

[0071] 4) Finding the node index: Use the strcmp function to compare each element of node_name with the startNode string. When the first identical element is found, use the find function to get the index of that element and assign this index to the startIndex variable (i.e., the index of the starting node). The endIndex (i.e., the index of the ending node) is calculated similarly. startIndex and endIndex represent the indices of the starting and ending nodes in the node_name array, respectively.

[0072] 5) Update the pipeline connection matrix: Store the found node indices startIndex and endIndex in the corresponding rows of the edges matrix. In this way, the start and end node indices of each edge are recorded in the edges matrix.

[0073] Step 6: Normalize the pipe lengths, save the pipe connection relationships as the first npy file, and save the normalized pipe lengths as the second npy file.

[0074] The purpose of this step is to normalize the pipe length matrix `link_length` extracted in step 4 into a `link_length_norm` matrix, and save it as a pipe connection matrix and pipe length for easy reading by Python later.

[0075] Step 6 specifically includes the following execution steps:

[0076] 1) Data type conversion: Use the str2double function to convert the string in the link_length array to a numeric type for mathematical operations.

[0077] 2) Normalization calculation: The minimum and maximum values ​​of `link_length` are calculated using MATLAB's built-in `min` and `max` functions. Then, the pipe lengths are converted to values ​​between 0 and 1 using the min-max normalization formula. This step converts all pipe lengths to values ​​between 0 and 1, ensuring that the length data has a consistent weight in subsequent processing and is stored in the variable `link_length_norm`, which is beneficial for distance-based analysis and calculations.

[0078] 3) Outputting the pipeline connection matrix: Use the `write.NPY` function (command to save the array as an .npy file) to save the normalized pipeline connection matrix `edges` as an `edges.npy` file to the specified file path. This function stores the data in NumPy format, making it easy for graph neural networks in Python to read and process it.

[0079] 4) Outputting the pipe length file: Similar to saving the edge matrix, the write.NPY function is used to save the normalized pipe lengths link_length_norm as a pipe length matrix edges_weight.npy file to the specified path. This allows the pipe lengths to be used in subsequent research.

[0080] Step 7: Extract the catchment area mjjz, maximum imperviousness_doub, total width subWidth_doub, and maximum slope_doub of the catchment area associated with each node from the variable matrix newline in Step 1 for subsequent processing.

[0081] Step 7 specifically includes the following execution steps:

[0082] 1) Query data range: Use the contains and find functions to search the newline array for the positions of rows containing the keywords 'SUBCATCHMENTS' (i.e., the row containing the catchment area information) and 'SUBAREAS', and store them in variables lia33 and lia44 respectively.

[0083] Define the data range: Calculate the range of rows containing the catchment area data using the found row numbers. This is done by starting at the beginning row lia33 plus 3 (i.e., 3 rows below 'SUBCATCHMENTS') and ending at the end row lia44 minus 2 (i.e., 2 rows above 'SUBAREAS'), ensuring that descriptive content that is not data is skipped.

[0084] 2) Calculate the number of data rows: Calculate the number of rows occupied by the catchment area. The calculation formula is lia44-lia33-5+1. Since it includes itself, one must be added.

[0085] 3) Initialize the area storage variable: Use cell(0) to initialize an empty cell array mj, which is used to temporarily store the area string of each row.

[0086] 4) Initialize the area numerical matrix: Use zeros(0) to initialize an empty numerical array mjjz to store the area data after conversion to numerical values.

[0087] 5) Initialize temporary storage structure: Before the loop starts, an mj_all cell array is re-initialized for each iteration to temporarily store the string split by the expression.

[0088] 6) Regular expression string splitting: Use the regexp function and the \s+ regular expression to extract and split the data rows of each catchment area from the newline array. This regular expression splits the string based on one or more spaces.

[0089] 7) Extract specific attributes: For each catchment area, extract the catchment area, maximum imperviousness (variable imperviousness), total width (variable subWidth), and maximum slope (variable slope) from the segmented result mj_all, and store them in the corresponding arrays respectively.

[0090] 8) Numeric Conversion: Use the str2double function to convert the catchment area data from string to number and store it in the mjjz array. Convert the string data of maximum imperviousness, total width, and maximum slope into numerical values ​​and store them in the imperviousness_doub, subWidth_doub, and slope_doub arrays, respectively.

[0091] Step 8: Normalize the catchment area mjjz, total width subWidth_doub, maximum imperviousness_doub, and maximum slope_doub of the catchment area extracted in Step 7.

[0092] Step 8 specifically includes the following execution steps:

[0093] 1) Normalized area data: The area data in the mjjz array is converted into values ​​between 0 and 1 using the minimum-maximum normalization formula, where min(mjjz) and max(mjjz) represent the minimum and maximum values ​​in the array, respectively.

[0094] 2) Normalized total width: The minimum-maximum normalization formula is applied to the subWidth_doub array to ensure that the data are on the same order of magnitude, which facilitates comparison and further processing.

[0095] 3) Adjust the maximum imperviousness and maximum slope ratio: Since the maximum imperviousness and maximum slope may be provided as percentages (e.g., 100 means 100%), divide them by 100 to convert them to a ratio of 0 to 1.

[0096] Step 9: Construct an X_combine data matrix containing information on catchment area, total width, maximum impermeability, and maximum slope.

[0097] Step 9 specifically includes the following execution steps:

[0098] 1) Matrix initialization: The X_combine matrix is ​​initialized using zeros(988,4) to store four parameters corresponding to the 988 nodes: total area, maximum impermeability, total width, and maximum slope. This matrix dimension is based on the assumption of 988 nodes.

[0099] 2) Node traversal: Use a for loop to traverse from 1 to 988 using a counter i, representing each node.

[0100] 3) Get the name of the current node: Use the index to get the name of the current node (i.e., get the i-th node) from the node_name array.

[0101] 4) Find matching catchment areas: Use the strcmp and find functions to find the indices of all entries in the LidToNode array that match the current node name (i.e., the name of the i-th node obtained in the previous step).

[0102] 5) Condition judgment: Check whether the found index array indices is empty, that is, whether there is a catchment area associated with the current node.

[0103] 6) Set default values: If indices is empty, it means that no catchment area is associated with this node, so set all values ​​in the current row of the X_combine matrix to 0.

[0104] 7) Cumulative area and total width: If indices is not empty, calculate the sum of the area (mjjz) and total width (subWidth_doub) of all matched catchment areas, i.e., the variables mjjz_sum and subWidth_sum.

[0105] 8) Calculate the maximum value: Calculate the maximum value of the maximum imperviousness (imperviousness_doub) and the maximum slope (slope_doub) of all matched catchment areas, i.e., the variables imperviousness_max and slope_max.

[0106] 9) Fill the result matrix: Fill the corresponding columns of the X_combine matrix with these calculated result variables mjjz_sum, imperviousness_max, subWidth_sum and slope_max (total area, maximum imperviousness, total width, and maximum slope).

[0107] Step 10: Establish a catchment area name matrix and extract the corresponding outlets for each area; that is, extract the catchment area name and its corresponding outlet information LidToNode1 array from the variable matrix newline in Step 1 and save it.

[0108] Step 10 specifically includes the following execution steps:

[0109] 1) Initialize the name storage structure: Use zeros(0) to initialize an empty numeric array mcjz to store the catchment area names after they have been converted to numeric values.

[0110] 2) Loop through the data rows of the catchment area: Use a for loop to iterate from the data row of the first catchment area (i.e., the data row below the 'SUBCATCHMENTS' row) to the data row of the last catchment area.

[0111] 3) Regular expression string splitting: Use the regexp function and the \s+ regular expression to extract and split the data rows of each catchment area from the newline array.

[0112] 4) Extract name data: For each catchment area, extract the first element (i.e. the area number name) from the segmented result mc_all and store it in the mc array.

[0113] 5) Name storage: The contents of the mc array are directly assigned to the mcjz array. Here, mcjz is used to store the name of the catchment area, which is suitable for cases containing text.

[0114] 6) Initialize the outlet storage structure: Use cell(0) to initialize an empty cell array LidToNode to store the outlet information corresponding to each catchment area.

[0115] 7) Loop through the data rows of the catchment area: Use a for loop to iterate from the data row of the first catchment area to the data row of the last catchment area.

[0116] 8) Regular expression string splitting: Use the regexp function and the \s+ regular expression to extract and split the data rows of each catchment area from the newline array.

[0117] 9) Extracting discharge outlet data: For each catchment area, extract the third element (i.e., the corresponding number of the discharge outlet) from the segmented corresponding result and store it in the LidToNode array.

[0118] 10) String to number conversion: Use the str2double function to convert the output data in the LidToNode array from string to number and store it in the LidToNode1 array.

[0119] 11) Save data: Use the write.NPY function to save the LidToNode1 array as a NumPy file.

[0120] Step 11: Extract outlet data, that is, extract outlet data from the variable matrix newline in Step 1 and mark whether the node is an outlet in the data matrix X_combine established in Step 11.

[0121] Step 11 specifically includes the following execution steps:

[0122] 1) Query the range of outlet data: Use the `contains` and `find` functions to retrieve rows containing the label '[OUTFALLS]' (i.e., the starting row of the outlet data corresponding to the node). Offset four rows down (i.e., the actual data begins four rows below the '[OUTFALLS]' label). This marks the beginning of the outlet data, and the location information is stored in the variable `outfall_node`. Similarly, use the `contains` and `find` functions to locate the label '[CONDUITS]', which marks the end of the outlet data. Offset two rows up (i.e., the actual data ends two rows above the '[CONDUITS]' label) to accurately define the end of the data range, and store the location information in the variable `outfall_node_end`.

[0123] 2) Calculate the number of data rows: Use the difference between the start row and the end row plus one to calculate the total number of outlets (i.e., num_outfall = outfall_node_end - outfall_node + 1), and store it in the variable num_outfall.

[0124] 3) Traverse the discharge outlet data rows: Use a for loop to iterate from the first discharge outlet data row to the last discharge outlet data row.

[0125] 4) Initialize the outlet storage array: Use cell(0) to initialize an empty cell array outlet_nodeX to temporarily store the area string for each row.

[0126] 5) Regular expression string splitting: Use the regexp function and the \s+ regular expression to extract and split the data lines of each output from the newline array.

[0127] 6) Extract outlet name and bottom elevation: For each outlet, extract the first element (outlet name) and the second element (inner bottom elevation) from the segmented result outfall_nodeX, and store them in the outfall_node_name and outfall_bottomElevation arrays respectively.

[0128] 7) Set the fifth column value to zero: Initialize the value of each node in the fifth column of the X_combine matrix to 0, in preparation for recording the existence of the discharge outlet. This step sets the basic state, assuming that initially no node is a discharge outlet.

[0129] 8) Node traversal: Use a for loop to traverse each outlet, and the number of loops is determined by num_outfall (total number of outlets).

[0130] 9) Extract the current outlet name: Use array indexing to get the name of the current outlet from the outfall_node_name array and store it in the outfall_node_now variable.

[0131] 10) Find the node index: Use the strcmp function to compare node_name (an array of all node names) with the outfall_node_now array to find the index of the node whose name matches. The find function returns the position of this matching node in the node_name array.

[0132] 11) Set the outlet identifier: Set the value to 1 at the index position of the node found in the fifth column of the X_combine matrix to mark the node as an outlet.

[0133] Step 12: Extract the node elevation and node depth information from the variable matrix newline in Step 1 and perform normalization to obtain the Node_bottomElevation and Node_MaxDepth_norm arrays.

[0134] Step 12 specifically includes the following execution steps:

[0135] 1) Querying the data range: Use the `contains` and `find` functions to retrieve rows containing the label '[JUNCTIONS]' (i.e., the starting row containing the data information of the node's elevation and depth). Offset three rows down (i.e., the actual data begins three rows below the '[JUNCTIONS]' label), marking the start of the outflow data. Store this location information in the variable `Junctions`. Similarly, use the `contains` and `find` functions to locate the label '[OUTFALLS]', which marks the end of the outflow data. Offset two rows up (i.e., the actual data ends two rows above the '[OUTFALLS]' label) to accurately define the end of the data range. Store this location information in the variable `outfall_node_new`.

[0136] 2) Calculate the total number of nodes involved: Use the difference between the start and end rows plus one to calculate the total number of nodes involved, and store it in num_Junctions.

[0137] 3) Traverse the node data rows: Use a for loop to iterate from the first node data row to the last node data row.

[0138] 4) Regular expression string splitting: Use the regexp function and the \s+ regular expression to extract and split the data rows of each node from the newline array and store them in the variable Junctions_nodeX.

[0139] 5) Extract node elevation and node depth: For each node, extract the second element (node ​​elevation) and the third element (node ​​depth) from the segmented result Junctions_nodeX, and store them in the Junctions_bottomElevation and Junctions_MaxDepth arrays, respectively.

[0140] 6) Merge node elevation data: Use array concatenation to merge the Junctions_bottomElevation and outfall_bottomElevation arrays.

[0141] 7) Fill missing node depth values: For exit nodes, there is no maximum depth data, so the constant '10' is used instead. The repmat function is used to generate an array with '10' elements, the length of which is the number of exit nodes (num_node-length(Junctions_MaxDepth)), and it is merged with the Junctions_MaxDepth array.

[0142] 8) Convert node elevation and node depth data to numerical type: Convert the strings in the Node_bottomElevation and Node_MaxDepth arrays to double-precision floating-point numbers.

[0143] 9) Normalize node elevation: Calculate the normalized values ​​of the Node_bottomElevation and Node_MaxDepth_norm arrays, scaling all node elevation data to between 0 and 1.

[0144] Step 13: Construct the final X_combine_final matrix, which is to integrate the normalized node X and Y coordinate data from Step 3 and the normalized node elevation and depth data from Step 12, along with the Node_bottomElevation and Node_MaxDepth_norm arrays, into the X_combine matrix filled in Step 9 and save it as an NPY file for subsequent data extraction from Python graph neural networks.

[0145] Step 13 specifically includes the following process steps:

[0146] 1) Merge Data: Merge the X_combine matrix with the normalized node positions 'node_positionX_norm' and 'node_positionY_norm', as well as the normalized node elevation arrays 'Node_bottomElevation_norm' and 'Node_MaxDepth_norm'. An array transpose is used for each matrix here to ensure all data columns are correctly aligned.

[0147] 2) Data merging: By concatenating arrays, different data sources are integrated into a larger data matrix X_combine_final, which facilitates unified processing and analysis.

[0148] 3) Save the data: Use the write.NPY function to save the X_combine_final matrix as a NumPy file. The specific columns of the X_combine_final matrix include the X and Y positions of each node, the catchment area, the maximum impermeability, the total width, the maximum slope, whether it is an outlet, the node elevation, and the node depth data.

[0149] As an optimization, the second step of this method specifically includes the following steps:

[0150] Step a: Load and initialize the environment; including the following execution steps;

[0151] 1) Set up the environment;

[0152] Import the following libraries:

[0153] Numpy library: used for numerical computation;

[0154] The Torch library and the torch_geometric.data library are used for processing graph neural network data structures.

[0155] The Networkx and matplotlib libraries are used for graphical visualization.

[0156] 2) Set the environment variable os.environ['KMP_DUPLICATE_LIB_OK'] = 'TRUE' to resolve potential parallel processing library conflicts.

[0157] Step b: Load the node, edge, and weight data converted from the MATLAB software; that is, load the pipeline connections, pipeline length data, and node features required to construct the graph structure from the edges.npy, edges_weight.npy, and X_combine_final.npy files created by the MATLAB software.

[0158] Step b specifically includes the following execution steps:

[0159] 1) Create a variable `edges` to determine the pipe connection relationships = `np.load(r'C:\...\edges.npy')`: Loads the pipe network connection relationships between catchment areas. This is a two-dimensional array, where each row contains two integers, representing the start and end node numbers and names of the pipe connection.

[0160] 2) Create variables, read data, and determine the pipeline length: edges_weight = np.load(r'C:\...\edges_weight.npy'): Loads the normalized pipeline length. This is a one-dimensional array with length num_edges.

[0161] 3) `x_combine_final = np.load(r'C:\...\X_combine_final.npy')`: Loads the node feature matrix, including relevant information for each catchment area. The columns of the `X_combine_final` matrix specifically include the node's catchment area, maximum impermeability, total width, maximum slope, whether it is a discharge outlet, node X and Y positions, node elevation, and node depth data. Through these loading steps, the code successfully obtains all the node features, pipe connection relationships, and pipe length data required to construct the graph structure from the external file, preparing for the next step of processing.

[0162] Step c: Construct input data based on graph neural networks, converting the loaded node features and edge information into a format usable by graph neural networks (GNNs).

[0163] Step c specifically includes the following execution steps:

[0164] 1) Execute device = torch.device("cuda" if torch.cuda.is_available() else "cpu"): Move data to the GPU (graphics processing unit) or CPU (central processing unit) depending on CUDA availability.

[0165] 2) Execute `x_combine = torch.tensor(x_combine_final, dtype = torch.float).to(device)`: This creates the variable `x_combine` to store the PyTorch tensor after converting the node feature matrix and moves it to the device (GPU / CPU). `torch.tensor` is the command that converts the data into a PyTorch tensor.

[0166] 3) Executing `edge_index = torch.tensor(edges.T-1, dtype = torch.long).to(device)`: This creates the `edge_index` variable, converts the edge index matrix into a PyTorch tensor, and moves it to the corresponding device. Note that `edges.T` is transposed here, with dimensions (2, num_edges). (Subtracting 1 from the edge index is to adjust the node numbering from 1-based to 0-based, conforming to Python's indexing standard.)

[0167] 4) Execute `edge_attr = torch.tensor(edges_weight, dtype = torch.float).to(device)`: This creates the `edge_attr` variable and converts the pipeline length (pipeline length) into a PyTorch tensor. At this point, all the matrix data required by the graph neural network has been loaded.

[0168] 5) Use the Data(x=x_combine,edge_index=edge_index,edge_attr=edge_attr) function to package node features, edge information, and pipeline length into a graph data object and store it in the variable data.

[0169] Step d: Extract the node locations of the graph and process isolated nodes in the graph to ensure the integrity of the graph structure.

[0170] Step d specifically includes the following execution steps:

[0171] 1) Create a variable node_positions = x_combine[:,[5,6]].cpu().numpy(): Extract the X and Y coordinate information of the nodes. The 6th and 7th columns of x_combine store the planar coordinates of each node, which are used to locate the position of the nodes on the graph.

[0172] 2) Handling isolated nodes, the specific process is as follows:

[0173] a) Use NetworkX to build a directed graph DiGraph and filter out isolated nodes without edges;

[0174] b) Use edge_index.cpu().numpy().T to convert the edge information into NumPy format and store it in edges_numpy;

[0175] c) Obtain the set of nodes connected to the edges using edges_numpy.flatten() and store it in the connected_nodes variable;

[0176] 3) Execute G.add_edges_from((u,v)for u,v in edges_numpy if u in connected_nodes and v in connected_nodes): Add pipeline connections (i.e. edges) to the network graph G, which only contains connected nodes.

[0177] 4) Create a variable area_column = x_combine[:len(G.nodes),0].cpu().numpy(): Extract the area information of the nodes.

[0178] 5) Create a variable `outlet_column = x_combine[:len(G.nodes),4].cpu().numpy()`: Extract the boolean value indicating whether a node is an outlet. Based on this information, set the outlet node to blue, the default color to orange, and the color of points with an area of ​​0 to light red. The colors of other nodes change according to their area.

[0179] 6) Set colors: Set color rules based on the node's area and outlet attributes. The specific process is as follows;

[0180] If the node is an outlet (is_outlet == 1), set it to blue (0.33, 0.66, 0.89, 0.8); if the area is 0 (area == 0), set it to light red (0.83, 0.37, 0.33, 0.8); for other nodes, use the default orange (0.96, 0.73, 0.48, 0.8); and store the color of each node in a list node_colors.

[0181] 7) Determine node positions: Use the extracted node coordinates to generate a node position dictionary pos. The key of the dictionary is the node index, and the value is the x and y coordinates of the node.

[0182] Step e: Visualize the graphic, make detailed adjustments to the visualized parts of the image to make the information of nodes and edges intuitively visible.

[0183] Step e specifically includes the following execution steps:

[0184] 1) Draw nodes:

[0185] Use the nx.draw_networkx_nodes (draw nodes in the graph command) function to draw nodes.

[0186] The pos instruction maps each node to its position (usually two-dimensional coordinates).

[0187] The node_color directive specifies the color for each node.

[0188] The node size (in points) is set using the node_size directive.

[0189] The alpha command was used to set the transparency of the color.

[0190] The edgecolors directive is used to set the color of the node border.

[0191] 2) Draw the edges and arrows:

[0192] Use the nx.draw_networkx_edges function to draw edges.

[0193] The arrowstyle and arrowsize parameters control the style and size of the arrow.

[0194] The edge color and total width are set using the edge_color and width parameters.

[0195] The connectionstyle parameter controls the bending style of the edges.

[0196] 3) Add legend:

[0197] Use the mpatches.Patch directive to create tags that match the node's color.

[0198] Use the plt.legend function to add a legend to the graph.

[0199] The loc parameter sets the position of the legend.

[0200] The fontsize and prop parameters control the font size and font of the text in the legend.

[0201] Step f: Save the generated graphic as a high-quality image file.

[0202] This step f specifically includes the following execution steps:

[0203] 1) Define the path to save the image: Create the output_path variable to determine the save location.

[0204] 2) Save the image: Use the savefig command to save the image, and use the format command to specify the image saving format as JPG and the resolution DPI as 600.

[0205] Compared to existing technologies, this method has the following advantages: Compared to other methods that directly utilize SWMM models for urban flooding research and LID (Light Detection and Isolation) construction schemes for sponge cities, this method can efficiently and accurately identify and transform the information data from SWMM models into data that can be directly recognized and used by graph neural networks. This saves a significant amount of time compared to importing the original model data into graph neural networks one by one. By converting SWMM model data into data that graph neural networks can directly recognize, this method solves the problem that traditional urban hydrological and hydraulic model data is difficult to directly use for efficient analysis and prediction by modern intelligent algorithms. By combining the simulation capabilities of SWMM for urban precipitation with the advantages of graph neural networks in complex network data analysis, this method provides more accurate technical support for urban water resource management, flood control, and infrastructure planning and research analysis.

[0206] In summary, this invention simplifies the data processing flow, enables rapid structuring of SWMM model data, and provides accurate and real-time analytical support for urban hydrological management. It represents a significant technological innovation for smart city construction and modern management. Attached Figure Description

[0207] Figure 1 This is a model image exported from the .inp file data of the SWMM software, which is the SWMM model established in Wanzhou District, Chongqing City, in a specific embodiment of the present invention.

[0208] Figure 2 for Figure 1The image is generated after the SWMM model is transformed using MATLAB and visualized using Python's graph neural network using the method described in this paper. Detailed Implementation

[0209] The present invention will now be described in further detail with reference to specific embodiments. Detailed implementation method:

[0211] An interactive method for converting SWMM model data into data that can be directly recognized by graph neural networks, first establishing an SWMM model of the urban area under study, dividing the watershed into zones, and exporting an .inp (text file with the .inp extension) file; characterized by further including the following steps:

[0212] Step 1: First, using MATLAB (a commercial mathematical software for data analysis), the .inp file of the SWMM model is read. The X-axis and Y-axis coordinates of each node are extracted and normalized. Then, the pipe connection relationships (i.e., information about the pipes and their two ends) and pipe length information are extracted. After extraction, the pipe connection relationship information is saved as the first .npy file (a binary file used to store array data), and the pipe length information is saved as the second .npy file. Next, the catchment area, maximum impermeability, total width, maximum slope, whether it is a discharge outlet, node elevation, and node depth data associated with each node are extracted and normalized. Finally, the node X and Y positions, catchment area, maximum impermeability, total width, maximum slope, whether it is a discharge outlet, node elevation, and node depth data are integrated and saved as a node feature matrix, which is then saved as the third .npy file.

[0213] Step 2: Use Python (a computer language) to visualize the .npy file.

[0214] Thus, in this invention, the node-related data, pipe connection relationships, and pipe length data are first normalized and saved as three different .npy files. This step transforms all data from the SWMM model's .inp file into a form that graph neural networks can directly recognize and use. Graph neural networks can help identify potential drainage problems in the area (such as waterlogging, sewage overflow, etc.), and can also help understand the flow process of water in the drainage system, predict future water level changes, and the susceptibility to urban flooding, thus better assisting researchers in assessing urban flood risks. Then, based on these three .npy files, visualization is implemented using Python software. In this step, isolated nodes (nodes without pipe connections to other nodes) are processed... The data has been processed to remove unnecessary information, transforming complex data into simpler and more intuitive graphics. This helps users quickly identify key nodes and pipes in the model, as well as the relationships and interactions between them. This process also makes it easier for users to identify nodes lacking catchment areas and outlets, aiding in decision-making optimization. For example, in urban flood risk assessments, it allows for a rapid understanding of the relative positions of various nodes in the urban drainage system and the direction of water flow. This enables designers to more intuitively add pipes to flood-prone areas and adjust nodes lacking catchment areas. Furthermore, it allows urban planners to better plan and adjust urban functional zones or emergency measures in flood-prone areas.

[0215] Therefore, this invention enables direct interaction between the SWMM model and Python's graph neural network using MATLAB software, facilitating the direct analysis of various urban flooding data and related research using graph neural network algorithms. By combining SWMM and GNN, higher levels of automation and intelligence can be achieved in the design, optimization, and operation management of urban drainage systems, effectively reducing human error and improving system response speed and disaster management capabilities.

[0216] In this scheme, a node refers to a connection point of the pipelines in the urban drainage network system. The connection point can be a diverter, storage unit, or outlet. These nodes play a key role in the network structure of the drainage system. They connect different links (such as pipes, channels, etc.) and allow water to flow or be stored between these links.

[0217] In this scheme, the X-axis and Y-axis coordinates of each node refer to the geometric coordinates of the node in two-dimensional space, used to describe its specific location in the drainage network within the model. The X and Y positions of the nodes are stored in node_positionX (variable matrix name) and node_positionY, respectively, and are normalized to generate node_positionX_norm and node_positionY_norm.

[0218] In this scheme, the catchment area associated with each node refers to the sum of the catchment areas of all regions converging at a node, representing the range of rainwater sources received by that node. In the model, the catchment area directly affects the input water volume of a node and is one of the key determinants of node flow rate. A larger catchment area means that the node needs to handle a larger volume of rainwater, potentially putting higher pressure on downstream pipelines. The catchment area is represented by the variable `mjjz` in the initial step and is then subjected to min-max normalization in subsequent processing to generate the normalized result `mjjz_norm`.

[0219] In this scheme, the maximum imperviousness associated with each node refers to the proportion of impervious surfaces (such as buildings, roads, etc.) within the catchment area associated with a node to the total area. It reflects the portion of rainwater runoff that cannot permeate into the ground within the node's catchment area. A higher maximum imperviousness at a node results in a larger volume of surface runoff collected, increasing the burden on downstream pipe networks. In the steps, this physical quantity is stored as the variable `imperviousness_doub` and normalized to generate `imperviousness_norm`.

[0220] In this scheme, the total width associated with each node (Subcatchment Width) refers to the total width of the water flow path within the catchment area associated with a node, describing the degree of dispersion of water flow converging at the node. A larger total width indicates a shorter water flow path and a faster water flow velocity, thus potentially resulting in a greater water flow impact received by the node. This physical quantity is represented by the variable subWidth_doub in the steps, and the normalized result is stored as subWidth_norm.

[0221] In this scheme, the maximum slope associated with each node refers to the maximum topographic slope of the catchment area associated with a node, representing the acceleration capacity of the water flow within the area. A larger slope results in faster water flow to the node, potentially causing greater flow pressure on the node. A smaller slope leads to slower water flow and longer convergence time. This physical quantity is represented by slope_doub and normalized to generate slope_norm.

[0222] In the scheme, the outlet (Is Outlet) associated with each node indicates whether a node is the final discharge point of the drainage system. It is stored as a Boolean value, with 0 representing a normal node and 1 representing an outlet node. Outlet nodes are critical points in the entire drainage system, directly affecting drainage efficiency. For outlet nodes, water is discharged from the system to the external environment; non-outlet nodes are merely nodes for water flow transmission within the pipe network. In the steps, this attribute is stored in the fifth column of the matrix X_combine to identify the function of the node.

[0223] In this scheme, the node elevation associated with each node refers to the ground height of a node, reflecting the terrain features at the node's location. Elevation affects the gravity flow direction of water and is a key parameter determining whether water can be discharged smoothly. Elevation data is stored as Node_bottomElevation and normalized to generate Node_bottomElevation_norm for subsequent model calculations.

[0224] In this scheme, the node depth associated with each node refers to the maximum depth from the ground of that node to the bottom of the drainage pipe. It represents the node's maximum water capacity; the greater the depth, the more water the node can hold. Node depth is stored as Node_MaxDepth and normalized to generate Node_MaxDepth_norm.

[0225] The first step of this method specifically includes the following steps:

[0226] Step 1: Open the SWMM model using MATLAB software and extract the information data from the inp file; convert all data content into a variable matrix newline (variable matrix name) for subsequent processing.

[0227] The specific implementation process of step 1 is as follows:

[0228] 1) Set the simulation step size: Define a variable time_step with a value of 5, which means that the simulation is performed once every 5 minutes.

[0229] 2) Clean up the environment: Use the clear and clc commands to clear variables and command windows in the MATLAB environment to prepare for new file operations.

[0230] 3) File path and mode: Open a .inp file containing SWMM model data using the fopen (open file and set read / write mode command) function. The file is opened in read / write mode (r+) to allow modification of the file content.

[0231] 4) Initialize variables: Initialize variable i and array newline. newline is used to store each line of data read from the file.

[0232] 5) Loop reading: Use a while loop and the feof function to check if the file has reached the end. This loop remains active until the file has been completely read.

[0233] 6) Read line by line: Use the fgetl (command to read file content line by line) function to read the file content line by line. After each line is read, the variable i is incremented by 1, and the read line is stored in the newline array.

[0234] 7) Close file operations: Use the `fclose(fileID)` command to close previously opened files. This is an important operation used to release system resources and ensure that all changes are saved.

[0235] Step 2: Extract the X and Y coordinate information of the nodes. That is, extract the node name and coordinate information from the variable matrix newline in Step 1, and convert it into a node number and name matrix node_name, node position X coordinate node_positionX, and node position Y coordinate node_positionY, so as to be used for the establishment of the graph structure.

[0236] Step 2, when implemented, includes the following operational steps:

[0237] 1) Initialize and find node positions: Use the `contains` function (command to check if a string array contains a specific substring) and the `find` function (command to find the index of an element that meets a certain condition) to find and locate the rows in the `newline` array that contain 'COORDINATES' (i.e., the row with the coordinates) and 'VERTICES', and store them in the variables `node_id` and `node_idend`, respectively. By finding the positions of these keywords, the start (3 rows below the row containing 'COORDINATES') and end (1 row above the row containing 'VERTICES') of the node data can be located.

[0238] 2) Calculate the number of nodes: Based on the start and end positions of the node data, calculate the total number of nodes. This is obtained by subtracting the start position plus one from the end position and storing it in the variable num_node.

[0239] 3) Loop to extract node data: Use a for loop to extract data from each node, starting from the beginning and according to the number of nodes.

[0240] 4) Data splitting using expressions: Use the regexp (a command to split strings using regular expressions) function and the expression \s+ to split each line of data. This allows you to extract node names and coordinate information. This expression splits the string based on spaces to obtain detailed node information.

[0241] 5) Store node information: Store the node number and name, the X-axis coordinate of the node position, and the Y-axis coordinate of the node position into the predefined variables node_name, node_positionX, and node_positionY, respectively.

[0242] Step 3: Normalize the X and Y coordinate data of the nodes. That is, convert the node X and Y coordinate information extracted in Step 2 into normalized values ​​and store them in the matrices node_positionX_norm and node_positionY_norm respectively to ensure that the data is within the range of 0 to 1.

[0243] Step 3, when implemented, includes the following operational steps:

[0244] 1) String to number conversion: Use the str2double (command to convert string to double) function to convert the node coordinates node_positionX and node_positionY from string format to double floating-point numbers.

[0245] 2) Use min-max normalization to process the coordinate data: Calculate the minimum and maximum values ​​of node_positionX and node_positionY respectively. These values ​​are used in the subsequent normalization process to ensure that all coordinates are scaled to the range between 0 and 1.

[0246] 3) Perform normalization: Normalize node_positionX and node_positionY by using a normalization formula to convert each coordinate value into a value in the range of 0 to 1, where the minimum coordinate becomes 0 and the maximum coordinate becomes 1. After calculation, store the data in the variables node_positionX_norm and node_positionY_norm respectively.

[0247] The normalization process is explained here:

[0248] Normalization is typically a process of scaling data values ​​of different features to a relatively consistent range to facilitate model processing or further data analysis.

[0249] The first step in the normalization process is to determine the minimum and maximum values. For data that needs to be normalized (such as the X and Y coordinates of a node, or the length of a pipe), the minimum and maximum values ​​of these data need to be calculated first.

[0250] Minimum value: Use the min() function to find the minimum value in the data.

[0251] Maximum value: Use the max() function to find the maximum value in the data.

[0252] The second step is to use the normalization formula, which is:

[0253]

[0254] In this formula:

[0255] original_value: This is the original data value, such as the original coordinates of a node or the original length of a pipe.

[0256] min_value: is the minimum value calculated in the first step.

[0257] max_value: is the maximum value calculated in the first step.

[0258] normalized_value: The normalized value, which usually falls within the range of [0,1].

[0259] Normalizing data ensures that all features are within the same magnitude range, which is crucial for subsequent data modeling and analysis. In particular, in graph neural network models, normalization can prevent certain feature values ​​from having an unbalanced impact on model training due to excessively large scales.

[0260] Through this normalization process, all data are scaled to the same interval [0,1], which facilitates subsequent model training or data visualization.

[0261] Step 4: Extract pipeline information from the variable matrix newline in Step 1, including the pipeline and its two end connection nodes and their lengths, and store them in the matrices link_name, graph_connection1 (starting end), graph_connection2 (ending end), and link_length.

[0262] This step specifically includes the following operational procedures:

[0263] 1) Find the key identifier: Use the `contains` and `find` functions to search the `newline` array for lines containing 'CONDUITS' (i.e., the lines containing pipeline data connecting two nodes). This marks the beginning of the pipeline data and is stored in the variable `link_id`. Use the `find` function to determine the position of this line and adjust the offset to determine the actual starting line of the data (i.e., the three lines below the line containing 'CONDUITS'), and store it in the variable `link_id_position`.

[0264] 2) Determine the end position of the data: Use the `contains` and `find` functions to locate the row containing 'XSECTIONS' and store it in the variable `link_idend`. This marks the end of the pipeline data. Adjust the offset to determine the actual end row of the data (i.e., the two rows above the row containing 'XSECTIONS') and store it in the variable `link_idend_position`.

[0265] 3) Calculate the number of pipes: Use the start and end positions to calculate (i.e., subtract link_id_position from link_id_position plus one) to get the total number of pipes.

[0266] 4) Loop through pipeline data: Use a for loop to iterate from the first pipeline data row to the last pipeline data row.

[0267] 5) Regular expression splitting of data: Split each line using the regexp function and \s + regular expression. This regular expression uses one or more spaces as delimiters to extract the pipe name and related connection nodes and length.

[0268] 6) Store the extracted pipeline data: The name of the extracted pipeline, the names of the two end connection nodes, and the length of the pipeline are stored in link_name, graph_connection1 (starting end), graph_connection2 (ending end), and link_length, respectively.

[0269] Step 5: Establish the pipeline connection matrix edges to store the starting and ending node index positions of each pipeline, so as to be used for connection relationship modeling in graph neural networks.

[0270] Step 5 specifically includes the following operational procedures:

[0271] 1) Edge Matrix Definition: Initialize a matrix of size num_link x 2 named edges using the zeros function (command to create an array of all zeros). This matrix stores the indices of the start and end nodes of each pipeline in the graph. Each row represents a pipeline, with the first column storing the index of the start node and the second column storing the index of the end node.

[0272] 2) Loop through the pipe data: Use a for loop, with variable i as a counter (i.e., which pipe), and traverse from the first pipe to the last pipe.

[0273] 3) Extract node names: Inside the loop, retrieve the names of the start node (startNode) and end node (endNode) of the current (i.e., the i-th) pipeline from the previously created graph_connection1 and graph_connection2 arrays.

[0274] 4) Finding the node index: Use the strcmp function to compare each element of node_name with the startNode string. When the first identical element is found, use the find function to get the index of that element and assign this index to the startIndex variable (i.e., the index of the starting node). The endIndex (i.e., the index of the ending node) is calculated similarly. startIndex and endIndex represent the indices of the starting and ending nodes in the node_name array, respectively.

[0275] 5) Update the pipeline connection matrix: Store the found node indices startIndex and endIndex in the corresponding rows of the edges matrix. In this way, the start and end node indices of each edge are recorded in the edges matrix.

[0276] Step 6: Normalize the pipe lengths, save the pipe connection relationships as the first npy file, and save the normalized pipe lengths as the second npy file.

[0277] The purpose of this step is to normalize the pipe length matrix `link_length` extracted in step 4 into a `link_length_norm` matrix, and save it as a pipe connection matrix and pipe length for easy reading by Python later.

[0278] Step 6 specifically includes the following execution steps:

[0279] 1) Data type conversion: Use the str2double function to convert the string in the link_length array to a numeric type for mathematical operations.

[0280] 2) Normalization calculation: The minimum and maximum values ​​of `link_length` are calculated using MATLAB's built-in `min` and `max` functions. Then, the pipe lengths are converted to values ​​between 0 and 1 using the min-max normalization formula. This step converts all pipe lengths to values ​​between 0 and 1, ensuring that the length data has a consistent weight in subsequent processing and is stored in the variable `link_length_norm`, which is beneficial for distance-based analysis and calculations.

[0281] 3) Outputting the pipeline connection matrix: Use the `write.NPY` function (command to save the array as an .npy file) to save the normalized pipeline connection matrix `edges` as an `edges.npy` file to the specified file path. This function stores the data in NumPy format, making it easy for graph neural networks in Python to read and process it.

[0282] 4) Outputting the pipe length file: Similar to saving the edge matrix, the write.NPY function is used to save the normalized pipe lengths link_length_norm as a pipe length matrix edges_weight.npy file to the specified path. This allows the pipe lengths to be used in subsequent research.

[0283] Step 7: Extract the catchment area mjjz, maximum imperviousness_doub, total width subWidth_doub, and maximum slope_doub of the catchment area associated with each node from the variable matrix newline in Step 1 for subsequent processing.

[0284] Step 7 specifically includes the following execution steps:

[0285] 1) Query data range: Use the contains and find functions to search the newline array for the positions of rows containing the keywords 'SUBCATCHMENTS' (i.e., the row containing the catchment area information) and 'SUBAREAS', and store them in variables lia33 and lia44 respectively.

[0286] Define the data range: Calculate the range of rows containing the catchment area data using the found row numbers. This is done by starting at the beginning row lia33 plus 3 (i.e., 3 rows below 'SUBCATCHMENTS') and ending at the end row lia44 minus 2 (i.e., 2 rows above 'SUBAREAS'), ensuring that descriptive content that is not data is skipped.

[0287] 2) Calculate the number of data rows: Calculate the number of rows occupied by the catchment area. The calculation formula is lia44-lia33-5+1. Since it includes itself, one must be added.

[0288] 3) Initialize the area storage variable: Use cell(0) to initialize an empty cell array mj, which is used to temporarily store the area string of each row.

[0289] 4) Initialize the area numerical matrix: Use zeros(0) to initialize an empty numerical array mjjz to store the area data after conversion to numerical values.

[0290] 5) Initialize temporary storage structure: Before the loop starts, an mj_all cell array is re-initialized for each iteration to temporarily store the string split by the expression.

[0291] 6) Regular expression string splitting: Use the regexp function and the \s+ regular expression to extract and split the data rows of each catchment area from the newline array. This regular expression splits the string based on one or more spaces.

[0292] 7) Extract specific attributes: For each catchment area, extract the catchment area, maximum imperviousness (variable imperviousness), total width (variable subWidth), and maximum slope (variable slope) from the segmented result mj_all, and store them in the corresponding arrays respectively.

[0293] 8) Numeric Conversion: Use the str2double function to convert the catchment area data from string to number and store it in the mjjz array. Convert the string data of maximum imperviousness, total width, and maximum slope into numerical values ​​and store them in the imperviousness_doub, subWidth_doub, and slope_doub arrays, respectively.

[0294] Step 8: Normalize the catchment area mjjz, total width subWidth_doub, maximum imperviousness_doub, and maximum slope_doub of the catchment area extracted in Step 7.

[0295] Step 8 specifically includes the following execution steps:

[0296] 1) Normalized area data: The area data in the mjjz array is normalized using the minimum-maximum normalization formula:

[0297]

[0298] Convert the numerical values ​​to values ​​between 0 and 1, where min(mjjz) and max(mjjz) represent the minimum and maximum values ​​in the array, respectively.

[0299] 2) Normalized total width: The minimum-maximum normalization formula is applied to the subWidth_doub array, as follows:

[0300]

[0301] This ensures that the data are on the same scale, making it easier to compare and process them further.

[0302] 3) Adjust the maximum imperviousness and maximum slope ratio: Since the maximum imperviousness and maximum slope may be provided as percentages (e.g., 100 means 100%), divide them by 100 to convert them to a ratio of 0 to 1.

[0303] Step 9: Construct an X_combine data matrix containing information on catchment area, total width, maximum impermeability, and maximum slope.

[0304] Step 9 specifically includes the following execution steps:

[0305] 1) Matrix initialization: The X_combine matrix is ​​initialized using zeros(988,4) to store four parameters corresponding to the 988 nodes: total area, maximum impermeability, total width, and maximum slope. This matrix dimension is based on the assumption of 988 nodes.

[0306] 2) Node traversal: Use a for loop to traverse from 1 to 988 using a counter i, representing each node.

[0307] 3) Get the name of the current node: Use the index to get the name of the current node (i.e., get the i-th node) from the node_name array.

[0308] 4) Find matching catchment areas: Use the strcmp and find functions to find the indices of all entries in the LidToNode array that match the current node name (i.e., the name of the i-th node obtained in the previous step).

[0309] 5) Condition judgment: Check whether the found index array indices is empty, that is, whether there is a catchment area associated with the current node.

[0310] 6) Set default values: If indices is empty, it means that no catchment area is associated with this node, so set all values ​​in the current row of the X_combine matrix to 0.

[0311] 7) Cumulative area and total width: If indices is not empty, calculate the sum of the area (mjjz) and total width (subWidth_doub) of all matched catchment areas, i.e., the variables mjjz_sum and subWidth_sum.

[0312] 8) Calculate the maximum value: Calculate the maximum value of the maximum imperviousness (imperviousness_doub) and the maximum slope (slope_doub) of all matched catchment areas, i.e., the variables imperviousness_max and slope_max.

[0313] 9) Fill the result matrix: Fill the corresponding columns of the X_combine matrix with these calculated result variables mjjz_sum, imperviousness_max, subWidth_sum and slope_max (total area, maximum imperviousness, total width, and maximum slope).

[0314] Step 10: Establish a catchment area name matrix and extract the corresponding outlets for each area; that is, extract the catchment area name and its corresponding outlet information LidToNode1 array from the variable matrix newline in Step 1 and save it.

[0315] Step 10 specifically includes the following execution steps:

[0316] 1) Initialize the name storage structure: Use zeros(0) to initialize an empty numeric array mcjz to store the catchment area names after they have been converted to numeric values.

[0317] 2) Loop through the data rows of the catchment area: Use a for loop to iterate from the data row of the first catchment area (i.e., the data row below the 'SUBCATCHMENTS' row) to the data row of the last catchment area.

[0318] 3) Regular expression string splitting: Use the regexp function and the \s+ regular expression to extract and split the data rows of each catchment area from the newline array.

[0319] 4) Extract name data: For each catchment area, extract the first element (i.e. the area number name) from the segmented result mc_all and store it in the mc array.

[0320] 5) Name storage: The contents of the mc array are directly assigned to the mcjz array. Here, mcjz is used to store the name of the catchment area, which is suitable for cases containing text.

[0321] 6) Initialize the outlet storage structure: Use cell(0) to initialize an empty cell array LidToNode to store the outlet information corresponding to each catchment area.

[0322] 7) Loop through the data rows of the catchment area: Use a for loop to iterate from the data row of the first catchment area to the data row of the last catchment area.

[0323] 8) Regular expression string splitting: Use the regexp function and the \s+ regular expression to extract and split the data rows of each catchment area from the newline array.

[0324] 9) Extracting discharge outlet data: For each catchment area, extract the third element (i.e., the corresponding number of the discharge outlet) from the segmented corresponding result and store it in the LidToNode array.

[0325] 10) String to number conversion: Use the str2double function to convert the output data in the LidToNode array from string to number and store it in the LidToNode1 array.

[0326] 11) Save data: Use the write.NPY function to save the LidToNode1 array as a NumPy file.

[0327] Step 11: Extract outlet data, that is, extract outlet data from the variable matrix newline in Step 1 and mark whether the node is an outlet in the data matrix X_combine established in Step 11.

[0328] Step 11 specifically includes the following execution steps:

[0329] 1) Query the range of outlet data: Use the `contains` and `find` functions to retrieve rows containing the label '[OUTFALLS]' (i.e., the starting row of the outlet data corresponding to the node). Offset four rows down (i.e., the actual data begins four rows below the '[OUTFALLS]' label). This marks the beginning of the outlet data, and the location information is stored in the variable `outfall_node`. Similarly, use the `contains` and `find` functions to locate the label '[CONDUITS]', which marks the end of the outlet data. Offset two rows up (i.e., the actual data ends two rows above the '[CONDUITS]' label) to accurately define the end of the data range, and store the location information in the variable `outfall_node_end`.

[0330] 2) Calculate the number of data rows: Use the difference between the start row and the end row plus one to calculate the total number of outlets (i.e., num_outfall = outfall_node_end - outfall_node + 1), and store it in the variable num_outfall.

[0331] 3) Traverse the discharge outlet data rows: Use a for loop to iterate from the first discharge outlet data row to the last discharge outlet data row.

[0332] 4) Initialize the outlet storage array: Use cell(0) to initialize an empty cell array outlet_nodeX to temporarily store the area string for each row.

[0333] 5) Regular expression string splitting: Use the regexp function and the \s+ regular expression to extract and split the data lines of each output from the newline array.

[0334] 6) Extract outlet name and bottom elevation: For each outlet, extract the first element (outlet name) and the second element (inner bottom elevation) from the segmented result outfall_nodeX, and store them in the outfall_node_name and outfall_bottomElevation arrays respectively.

[0335] 7) Set the fifth column value to zero: Initialize the value of each node in the fifth column of the X_combine matrix to 0, in preparation for recording the existence of the discharge outlet. This step sets the basic state, assuming that initially no node is a discharge outlet.

[0336] 8) Node traversal: Use a for loop to traverse each outlet, and the number of loops is determined by num_outfall (total number of outlets).

[0337] 9) Extract the current outlet name: Use array indexing to get the name of the current outlet from the outfall_node_name array and store it in the outfall_node_now variable.

[0338] 10) Find the node index: Use the strcmp function to compare node_name (an array of all node names) with the outfall_node_now array to find the index of the node whose name matches. The find function returns the position of this matching node in the node_name array.

[0339] 11) Set the outlet identifier: Set the value to 1 at the index position of the node found in the fifth column of the X_combine matrix to mark the node as an outlet.

[0340] Step 12: Extract the node elevation and node depth information from the variable matrix newline in Step 1 and perform normalization to obtain the Node_bottomElevation and Node_MaxDepth_norm arrays.

[0341] Step 12 specifically includes the following execution steps:

[0342] 1) Querying the data range: Use the `contains` and `find` functions to retrieve rows containing the label '[JUNCTIONS]' (i.e., the starting row containing the data information of the node's elevation and depth). Offset three rows down (i.e., the actual data begins three rows below the '[JUNCTIONS]' label), marking the start of the outflow data. Store this location information in the variable `Junctions`. Similarly, use the `contains` and `find` functions to locate the label '[OUTFALLS]', which marks the end of the outflow data. Offset two rows up (i.e., the actual data ends two rows above the '[OUTFALLS]' label) to accurately define the end of the data range. Store this location information in the variable `outfall_node_new`.

[0343] 2) Calculate the total number of nodes involved: Use the difference between the start and end rows plus one to calculate the total number of nodes involved, and store it in num_Junctions.

[0344] 3) Traverse the node data rows: Use a for loop to iterate from the first node data row to the last node data row.

[0345] 4) Regular expression string splitting: Use the regexp function and the \s+ regular expression to extract and split the data rows of each node from the newline array and store them in the variable Junctions_nodeX.

[0346] 5) Extract node elevation and node depth: For each node, extract the second element (node ​​elevation) and the third element (node ​​depth) from the segmented result Junctions_nodeX, and store them in the Junctions_bottomElevation and Junctions_MaxDepth arrays, respectively.

[0347] 6) Merge node elevation data: Use array concatenation to merge the Junctions_bottomElevation and outfall_bottomElevation arrays.

[0348] 7) Fill missing node depth values: For exit nodes, there is no maximum depth data, so the constant '10' is used instead. The repmat function is used to generate an array with '10' elements, the length of which is the number of exit nodes (num_node-length(Junctions_MaxDepth)), and it is merged with the Junctions_MaxDepth array.

[0349] 8) Convert node elevation and node depth data to numerical type: Convert the strings in the Node_bottomElevation and Node_MaxDepth arrays to double-precision floating-point numbers.

[0350] 9) Normalized Node Elevation: Calculate the normalized values ​​of the Node_bottomElevation and Node_MaxDepth_norm arrays using the formula:

[0351]

[0352]

[0353] This process scales all node elevation data to between 0 and 1.

[0354] Step 13: Construct the final X_combine_final matrix, which is to integrate the normalized node X and Y coordinate data from Step 3 and the normalized node elevation and depth data from Step 12, along with the Node_bottomElevation and Node_MaxDepth_norm arrays, into the X_combine matrix filled in Step 9 and save it as an NPY file for subsequent data extraction from Python graph neural networks.

[0355] Step 13 specifically includes the following process steps:

[0356] 1) Merge Data: Merge the X_combine matrix with the normalized node positions 'node_positionX_norm' and 'node_positionY_norm', as well as the normalized node elevation arrays 'Node_bottomElevation_norm' and 'Node_MaxDepth_norm'. An array transpose is used for each matrix here to ensure all data columns are correctly aligned.

[0357] 2) Data merging: By concatenating arrays, different data sources are integrated into a larger data matrix X_combine_final, which facilitates unified processing and analysis.

[0358] 3) Save the data: Use the write.NPY function to save the X_combine_final matrix as a NumPy file. The specific columns of the X_combine_final matrix include the X and Y positions of each node, the catchment area, the maximum impermeability, the total width, the maximum slope, whether it is an outlet, the node elevation, and the node depth data.

[0359] In implementation, the second step of this method specifically includes the following steps:

[0360] Step a: Load and initialize the environment; including the following execution steps;

[0361] 1) Set up the environment;

[0362] Import the following libraries:

[0363] Numpy library: used for numerical computation;

[0364] The Torch library and the torch_geometric.data library are used for processing graph neural network data structures.

[0365] The Networkx and matplotlib libraries are used for graphical visualization.

[0366] 2) Set the environment variable os.environ['KMP_DUPLICATE_LIB_OK'] = 'TRUE' to resolve potential parallel processing library conflicts.

[0367] Step b: Load the node, edge, and weight data converted from the MATLAB software; that is, load the pipeline connections, pipeline length data, and node features required to construct the graph structure from the edges.npy, edges_weight.npy, and X_combine_final.npy files created by the MATLAB software.

[0368] Step b specifically includes the following execution steps:

[0369] 1) Create a variable `edges` to determine the pipe connection relationships = `np.load(r'C:\...\edges.npy')`: Loads the pipe network connection relationships between catchment areas. This is a two-dimensional array, where each row contains two integers, representing the start and end node numbers and names of the pipe connection.

[0370] 2) Create variables, read data, and determine the pipeline length: edges_weight = np.load(r'C:\...\edges_weight.npy'): Loads the normalized pipeline length. This is a one-dimensional array with length num_edges.

[0371] 3) `x_combine_final = np.load(r'C:\...\X_combine_final.npy')`: Loads the node feature matrix, including relevant information for each catchment area. The columns of the `X_combine_final` matrix specifically include the node's catchment area, maximum impermeability, total width, maximum slope, whether it is a discharge outlet, node X and Y positions, node elevation, and node depth data. Through these loading steps, the code successfully obtains all the node features, pipe connection relationships, and pipe length data required to construct the graph structure from the external file, preparing for the next step of processing.

[0372] Step c: Construct input data based on graph neural networks, converting the loaded node features and edge information into a format usable by graph neural networks (GNNs).

[0373] Step c specifically includes the following execution steps:

[0374] 1) Execute device = torch.device("cuda" if torch.cuda.is_available() else "cpu"): Move data to the GPU (graphics processing unit) or CPU (central processing unit) depending on CUDA availability.

[0375] 2) Execute `x_combine = torch.tensor(x_combine_final, dtype = torch.float).to(device)`: This creates the variable `x_combine` to store the PyTorch tensor after converting the node feature matrix and moves it to the device (GPU / CPU). `torch.tensor` is the command that converts the data into a PyTorch tensor.

[0376] 3) Executing `edge_index = torch.tensor(edges.T-1, dtype = torch.long).to(device)`: This creates the `edge_index` variable, converts the edge index matrix into a PyTorch tensor, and moves it to the corresponding device. Note that `edges.T` is transposed here, with dimensions (2, num_edges). (Subtracting 1 from the edge index is to adjust the node numbering from 1-based to 0-based, conforming to Python's indexing standard.)

[0377] 4) Execute `edge_attr = torch.tensor(edges_weight, dtype = torch.float).to(device)`: This creates the `edge_attr` variable and converts the pipeline length (pipeline length) into a PyTorch tensor. At this point, all the matrix data required by the graph neural network has been loaded.

[0378] 5) Use the Data(x=x_combine,edge_index=edge_index,edge_attr=edge_attr) function to package node features, edge information, and pipeline length into a graph data object and store it in the variable data.

[0379] Step d: Extract the node locations of the graph and process isolated nodes in the graph to ensure the integrity of the graph structure.

[0380] Step d specifically includes the following execution steps:

[0381] 1) Create a variable node_positions = x_combine[:,[5,6]].cpu().numpy(): Extract the X and Y coordinate information of the nodes. The 6th and 7th columns of x_combine store the planar coordinates of each node, which are used to locate the position of the nodes on the graph.

[0382] 2) Handling isolated nodes, the specific process is as follows:

[0383] a) Use NetworkX to build a directed graph DiGraph and filter out isolated nodes without edges;

[0384] b) Use edge_index.cpu().numpy().T to convert the edge information into NumPy format and store it in edges_numpy;

[0385] c) Obtain the set of nodes connected to the edges using edges_numpy.flatten() and store it in the connected_nodes variable;

[0386] 3) Execute G.add_edges_from((u,v)for u,v in edges_numpy if u in connected_nodes and v in connected_nodes): Add pipeline connections (i.e. edges) to the network graph G, which only contains connected nodes.

[0387] 4) Create a variable area_column = x_combine[:len(G.nodes),0].cpu().numpy(): Extract the area information of the nodes.

[0388] 5) Create a variable `outlet_column = x_combine[:len(G.nodes),4].cpu().numpy()`: Extract the boolean value indicating whether a node is an outlet. Based on this information, set the outlet node to blue, the default color to orange, and the color of points with an area of ​​0 to light red. The colors of other nodes change according to their area.

[0389] 6) Set colors: Set color rules based on the node's area and outlet attributes. The specific process is as follows;

[0390] If the node is an outlet (is_outlet == 1), set it to blue (0.33, 0.66, 0.89, 0.8); if the area is 0 (area == 0), set it to light red (0.83, 0.37, 0.33, 0.8); for other nodes, use the default orange (0.96, 0.73, 0.48, 0.8); and store the color of each node in a list node_colors.

[0391] 7) Determine node positions: Use the extracted node coordinates to generate a node position dictionary pos. The key of the dictionary is the node index, and the value is the x and y coordinates of the node.

[0392] Step e: Visualize the graphic, make detailed adjustments to the visualized parts of the image to make the information of nodes and edges intuitively visible.

[0393] Step e specifically includes the following execution steps:

[0394] 1) Draw nodes:

[0395] Use the nx.draw_networkx_nodes (draw nodes in the graph command) function to draw nodes.

[0396] The pos instruction maps each node to its position (usually two-dimensional coordinates).

[0397] The node_color directive specifies the color for each node.

[0398] The node size (in points) is set using the node_size directive.

[0399] The alpha command was used to set the transparency of the color.

[0400] The edgecolors directive is used to set the color of the node border.

[0401] 2) Draw the edges and arrows:

[0402] Use the nx.draw_networkx_edges function to draw edges.

[0403] The arrowstyle and arrowsize parameters control the style and size of the arrow.

[0404] The edge color and total width are set using the edge_color and width parameters.

[0405] The connectionstyle parameter controls the bending style of the edges.

[0406] 3) Add legend:

[0407] Use the mpatches.Patch directive to create tags that match the node's color.

[0408] Use the plt.legend function to add a legend to the graph.

[0409] The loc parameter sets the position of the legend.

[0410] The fontsize and prop parameters control the font size and font of the text in the legend.

[0411] Step f: Save the generated graphic as a high-quality image file.

[0412] This step f specifically includes the following execution steps:

[0413] 1) Define the path to save the image: Create the output_path variable to determine the save location.

[0414] 2) Save the image: Use the savefig command to save the image, and use the format command to specify the image saving format as JPG and the resolution DPI as 600.

[0415] The applicant further specified Wanzhou District of Chongqing as an example, and built an SWMM model of the city using SWMM software. The model image exported from the .inp file data can be found here. Figure 1 The image shows the nodes of the region and their corresponding catchment areas, connecting pipes, and outlets. However, it doesn't allow for a quick and intuitive determination of the corresponding outlet for each node, the pipe connections, or the direction of water flow. The applicant then used the aforementioned conversion methods to generate the image from the SWMM model, which was then processed using MATLAB for data conversion and visualized using Python's graph neural network. (See attached image.) Figure 2 As can be seen from this diagram, it displays the nodes and edges of the network graph, as well as the characteristic information of each node. This transforms complex data into a more concise and intuitive graphic, helping users to quickly identify key nodes and pipes in the model, as well as the relationships and interactions between them. This processing also makes it easier for users to discover nodes lacking catchment areas, pipe connections, and discharge outlets, helping them to optimize decision-making. For example, in the risk assessment of urban flooding disasters, it can quickly understand the relative positions of various nodes in the urban drainage system and the direction of water flow. This allows designers to more intuitively add pipes to flood-prone areas and adjust nodes lacking catchment areas. It also allows urban planners to better plan and adjust urban functional areas or emergency measures in flood-prone areas. Therefore, it facilitates subsequent research by researchers to analyze the network structure and the relationships between nodes.

[0416] Therefore, compared with existing technologies, the advantages of this method are as follows: Compared with other methods that directly utilize SWMM models for urban flooding research and sponge city LID construction scheme analysis, this method can efficiently and accurately identify and transform the information data of SWMM models into data that can be directly identified and used by graph neural networks. This saves a lot of time that would otherwise be spent importing the original model data into the graph neural network one by one. By converting SWMM model data into data that can be directly identified by graph neural networks, this method solves the problem that traditional urban hydrological and hydraulic model data is difficult to directly use for efficient analysis and prediction by modern intelligent algorithms. By combining the simulation capabilities of SWMM for urban precipitation with the advantages of graph neural networks in complex network data analysis, this method provides more accurate technical support for urban water resource management, flood control, and infrastructure planning and research analysis.

Claims

1. An interactive method for converting SWMM model data into data directly identified by a graph neural network, first establish a SWMM model of a study urban area, divide the catchment area in the model, and export the inp file; characterized in that, Further comprising the following steps: The first step specifically comprises the following steps: Step 1: Open the SWMM model using matlab software and extract the information data in the inp file; convert all data content into a variable matrix newline for subsequent processing; Step 2: Extract the node name and coordinate information from the variable matrix newline in step 1, convert them into the node number name matrix node_name, the node position X coordinate node_positionX, and the node position Y coordinate node_positionY for the establishment of the graph structure; Step 3: Convert the node X and Y coordinate information extracted in step 2 into normalized numerical values and save them in the matrices node_positionX_norm and node_positionY_norm respectively to ensure that the data is within the range of 0 to 1; Step 4: Extract the pipe information from the variable matrix newline in step 1, including the pipe and its two end connection nodes and its length and save them in the matrices link_name, graph_connection1, graph_connection2 and link_length; Step 5: Establish the pipe connection relationship matrix edges to save the starting and ending node index positions corresponding to each pipe for connection relationship modeling in the graph neural network; Step 6: Normalize the pipe length, save the pipe connection relationship as the first npy file, and save the normalized pipe length as the second npy file; Step 7: Extract the catchment area mjjz, maximum imperviousness imperviousness_doub, total width subWidth_doub and maximum slope slope_doub information of each node associated catchment area from the variable matrix newline in step 1 for subsequent processing; Step 8: Normalize the catchment area mjjz, total width subWidth_doub, maximum imperviousness imperviousness_doub and maximum slope slope_doub extracted in step 7; Step 9: Construct the X_combine data matrix containing the catchment area, total width, maximum imperviousness and maximum slope information; Step 10: Extract the catchment area name and its corresponding outlet information LidToNode1 array from the variable matrix newline in step 1 and save them; Step 11: Extract the outlet data from the variable matrix newline in step 1 and identify whether the node is an outlet in the data matrix X_combine established in step 11; Step 12: Extract the node elevation and node depth information from the variable matrix newline in step 1 and normalize them to obtain the Node_bottomElevation and Node_MaxDepth_norm arrays; Step 13: Build the final X_combine_final matrix, integrate the normalized node X, Y coordinate data in step 3 and the normalized node elevation and node depth data Node_bottomElevation and Node_MaxDepth_norm array in step 12 into the X_combine matrix filled in step 9 and save it as a third NPY file for subsequent data extraction of python graph neural network; Second step: use python software to visualize based on three npy files.

2. The interactive method of converting SWMM model data to data for direct identification by a graph neural network of claim 1, wherein The second step of the method specifically includes the following steps: Step a: load the initialization environment; Step b: load the node, edge and weight data converted from MATLAB software; that is, load the pipeline connection relationship and pipeline length data and node features required for building the graph structure from the edges.npy, edges_weight.npy, X_combine_final.npy files created by MATLAB software from external files; Step c: build input data based on graph neural network, convert the loaded node features and edge information into a format available for graph neural network GNN; Step d: extract the node position of the graph and process the isolated nodes in the graph to ensure the integrity of the graph structure; Step e: visualize the graph, and make detailed adjustments to the visual part of the picture to make the node and edge information intuitive and visible; Step f: save the generated graph as a high-quality picture file.

3. The interactive method of converting SWMM model data to data for direct identification by a graph neural network of claim 2, wherein Step b specifically includes the following execution steps: 1) Establish variable edges to determine pipeline connection relationship = np.load(r'C:\...\edges.npy'): load the pipeline network connection relationship between catchment areas; this is a two-dimensional array, where each row contains two integers representing the start and end node number names of the pipeline connection; 2) Establish variable edges_weight to read data to determine pipeline length = np.load(r'C:\...\edges_weight.npy'): load the normalized length of the pipeline; this is a one-dimensional array with a length of num_edges; 3) x_combine_final = np.load(r'C:\...\X_combine_final.npy'): load the node feature matrix, including the relevant information of each catchment area; the specific columns in the X_combine_final matrix include the catchment area of the node, the maximum impervious rate, the total width, the maximum slope, whether it is a outlet, the node X and Y position, the node elevation and the node depth data.

4. The interactive method of converting SWMM model data to data for direct identification by a graph neural network of claim 2, wherein Step c specifically includes the following execution steps: 1) Execute device = torch.device("cuda" if torch.cuda.is_available() else "cpu"): move data to GPU (computer graphics processor) or CPU (computer central processing unit) according to the availability of CUDA; 2) Execute x_combine=torch.tensor(x_combine_final, dtype=torch.float).to(device): establish the x_combine variable to save the converted PyTorch tensor of the node feature matrix, and move it to the device GPU or CPU; 3) Execute edge_index = torch.tensor(edges.T - 1, dtype=torch.long).to(device): establish the edge_index variable to convert the edge index matrix to a PyTorch tensor and move it to the corresponding device; 4) Execute edge_attr = torch.tensor(edges_weight, dtype=torch.float).to(device): establish the edge_attr variable to convert the pipe length to a PyTorch tensor; 5) Use the Data(x=x_combine, edge_index=edge_index, edge_attr=edge_attr) function to package the node features, edge information and pipe length into a graph data object and store it in the variable data.

5. The interactive method of converting SWMM model data to data for direct identification by a graph neural network of claim 2, wherein Step d specifically includes the following execution steps: 1) Establish the variable node_positions = x_combine[:, [5, 6]].cpu().numpy(): extract the X, Y coordinate information of the nodes; 2) Process isolated nodes, the specific process is: a) Use NetworkX to build a directed graph DiGraph and filter out isolated nodes without edges; b) Convert edge information to NumPy format using edge_index.cpu().numpy().T and store it in edges_numpy; c) Get the set of nodes connected to the edges by edges_numpy.flatten() and store it in the connected_nodes variable; 3) Execute G.add_edges_from((u, v) for u, v in edges_numpy if u in connected_nodes and v in connected_nodes): add pipe connection relationships to the network graph G, only including connected nodes; 4) Create variable area_column = x_combine[:len(G.nodes), 0].cpu().numpy(): extract the area information of the nodes; 5) Create variable outlet_column = x_combine[:len(G.nodes), 4].cpu().numpy(): extract the Boolean value of whether the node is an outlet; according to this information, set the outlet node to blue, set the default color to orange, and set the point with an area of 0 to light red, and the color of other nodes changes according to the area; 6) Set color: set the color rule according to the area and outlet attribute of the node, the specific process is as follows; If the node is an outlet, set it to blue; if the area is 0, set it to light red; for other nodes, use the default orange; and store the color of each node in the list node_colors; 7) Determine node position: use the extracted node coordinates to generate the node position dictionary pos, the key of the dictionary is the node index, and the value is the x, y coordinates of the node.

6. The interactive method of converting SWMM model data to data for direct identification by a graph neural network of claim 2, wherein Step e specifically includes the following execution steps: 1) Draw nodes: Draw nodes with the nx.draw_networkx_nodes function; Map each node to its position with the pos instruction; Specify the color of each node with the node_color instruction; Set the size of the node with the node_size instruction; Set the transparency of the color with the alpha instruction; Set the color of the node border with the edgecolors instruction; 2) Draw edges and arrows: Use the nx.draw_networkx_edges function to draw edges; Control the style and size of the arrow with the arrowstyle and arrowsize parameters; Set the color and total width of the edge with the edge_color and width parameters; Control the bending style of the edge with the connectionstyle parameter; 3) Add legend: Use the mpatches.Patch instruction to create a label matching the node color; Add the legend to the graph with the plt.legend function; Set the position of the legend with the loc parameter; Control the font size and font of the text in the legend with the fontsize and prop parameters.

Citation Information

Patent Citations

  • Defense method for radio signal identification countermeasure attacks

    CN111428817A

  • Urban rainwater drainage system automatic optimization method based on SWMM and MATLAB

    CN113190944A