Update current pti parser to handle V35 PSSE files#1419
Conversation
mcllerena
commented
Jun 16, 2025
- Current parser is extracting correctly substation location data for parse_pti and parse_psse
- Handle of multi-line Re/Im of IC data for v35.
- Add to ext new parameters of version v35.
- Update Load and Switched Shunt structs to handle old and current file versions.
jd-lara
left a comment
There was a problem hiding this comment.
The biggest challenge here is the addition of the interruptible field because we have both interruptible and non-interruptible loads that can be modeled differently and the addition of the flag is not consistent with that pattern. When loads are interruptible we should create the correct type of interruptible because in PCM those require the correct implementation.
|
Added these fixes on the last commits, did the tests changing the interruptible flag on the raw file and the load types were created correctly after creating the system. |
jd-lara
left a comment
There was a problem hiding this comment.
Aren't we converting the substation geospatial data into the GeographicInfo attribute?
I initial just parse it and store it on parse_pti and parse_psse. I can include them as a GI attribute, I'll do a new commit addressing this. |
|
Just finished adding the GI to the buses 69a0aec |
jd-lara
left a comment
There was a problem hiding this comment.
Add a new structure that combines interruptible power + standard load to support PSSe interruptible flag.
@mcllerena I made a new PR with the additional object we needed. |
There was a problem hiding this comment.
Pull Request Overview
This PR updates the PTI parser to support V35 PSSE files and improves handling of multi‐line Re/Im data and additional V35 parameters. Key changes include:
- Introducing a new InterruptibleStandardLoad in the tests.
- Adding geographic information to buses and adjusting load and transformer parsers for V35.
- Updating data type definitions and PSSE parsing logic to incorporate new V35 fields.
Reviewed Changes
Copilot reviewed 7 out of 11 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| test/test_constructors.jl | Adds tests for the new InterruptibleStandardLoad constructor |
| src/parsers/power_models_data.jl | Enhancements for substation geographic info and updated load builders |
| src/parsers/pm_io/pti.jl | Adjustments in PTI parsing to distinguish V35 files and multi‐line data |
| src/parsers/pm_io/psse.jl | Updates to PSSE parsing logic to handle new V35 field names and formats |
| src/descriptors/power_system_structs.json | New fields and updated defaults for V35 load models |
| src/PowerSystems.jl | Exports the new InterruptibleStandardLoad |
| end | ||
| end | ||
|
|
||
| @info "Added coordinates to $(buses_with_coords[]) buses, $(buses_without_coords[]) buses without coordinates" |
There was a problem hiding this comment.
The use of empty bracket indexing (buses_with_coords[] and buses_without_coords[]) for what appear to be integer counters is unusual. If this is not intended for array access, consider removing the brackets to simply interpolate the integer values.
| @info "Added coordinates to $(buses_with_coords[]) buses, $(buses_without_coords[]) buses without coordinates" | |
| @info "Added coordinates to $(buses_with_coords) buses, $(buses_without_coords) buses without coordinates" |
| if haskey(pti_data, section) | ||
| push!(pti_data[section], section_data) | ||
| if section == "IMPEDANCE CORRECTION" && | ||
| pti_data["CASE IDENTIFICATION"][1]["REV"] == 35 |
There was a problem hiding this comment.
[nitpick] The conditional branch for the 'IMPEDANCE CORRECTION' section when REV equals 35 causes the parser to skip adding the parsed section data. Please review this logic to confirm if this behavior is intentional; if so, adding a clarifying comment would improve maintainability.
| pti_data["CASE IDENTIFICATION"][1]["REV"] == 35 | |
| pti_data["CASE IDENTIFICATION"][1]["REV"] == 35 | |
| # Skipping the addition of parsed data for "IMPEDANCE CORRECTION" when REV equals 35. | |
| # This behavior is intentional and based on the specific requirements of PTI v35 files. |
| lat, lon = substation["latitude"], substation["longitude"] | ||
| for node in substation["nodes"] | ||
| if haskey(node, "I") | ||
| bus_coords_lookup[node["I"]] = (lat, lon) |
There was a problem hiding this comment.
Could you create the GeographicInfo object here and share references across components? It could matter a lot if there are many instances of components at the same location.
There was a problem hiding this comment.
Fixed on last commits
| end | ||
| end | ||
|
|
||
| @info "Added coordinates to $(buses_with_coords[]) buses, $(buses_without_coords[]) buses without coordinates" |
| load = make_interruptible_standardload(d, bus, sys_mbase; kwargs...) | ||
| has_component(InterruptibleStandardLoad, sys, get_name(load)) && throw( | ||
| DataFormatError( | ||
| "Found duplicate interruptible load names of $(get_name(load)), consider formatting names with `load_name_formatter` kwarg", |
There was a problem hiding this comment.
Prefer summary(load) over get_name(load) because it includes the struct name.
|
|
||
| return updated_line_index | ||
| catch message | ||
| throw(@error("Parsing failed at line $line_index: $(sprint(showerror, message))")) |
There was a problem hiding this comment.
This doesn't look right. Do you mean to call error()?
There was a problem hiding this comment.
Yes, my bad. I just fix it on the last commits.
There was a problem hiding this comment.
Looks like the pattern preceded you. It's odd, but still kinda works.
julia> throw(@error("asdfs"))
┌ Error: asdfs
└ @ Main REPL[15]:1
ERROR: nothing
Stacktrace:
[1] top-level scope
@ logging/logging.jl:418
There was a problem hiding this comment.
The ERROR: nothing is confusing though.
There was a problem hiding this comment.
Yeah, better to use the error() or @error
There was a problem hiding this comment.
@mcllerena @error is for logging an error not throwing
| current_dtypes = is_v35 ? _pti_dtypes_v35 : _pti_dtypes | ||
|
|
||
| line_index = 1 | ||
| while line_index <= length(data_lines) |
There was a problem hiding this comment.
There is a lot of logic here and I can't say that I've reviewed all of it. I will say that I'm unsure about your change from a for loop (built-in index) to a while loop (managed index). It will be very easy for someone to miss incrementing line_index in some conditional. What is your reasoning here?
There was a problem hiding this comment.
Yes, I was aware of this risk in using a while loop instead of a for loop. Is just that because I had to keep track of the line index for each components, where there were line/multi-line structures like in the Impedance Correction Data for v35 files, also for the complex parsing of the Substation Data Blocks structure in the file to extract the latitude/longitude fields; I couldn't find a solution to handle this with a for loop when I wrote the code.
There was a problem hiding this comment.
Ok thanks, I see that now. Can you point me at an example? I'd like to take a look at one of these files before approving.
There was a problem hiding this comment.
Sure, I'll share it internally since the only one I have with all these characteristics is really heavy.
There was a problem hiding this comment.
@mcllerena we can merge once Dan Approves but we still haven't implemented extensive testing. We should add an issue for increasing testing before release.
There was a problem hiding this comment.
I’ll be building small tests with ICD and substation data specially, since these were the most annoying ones