This is a rough mapping visualisation of Energex Network in Noosa LGA

TO DO Add some basic reference info re the source of this data

And other script has been run to capture the data

References

Ergon services are also available

I used this Blog post to write code to access the ArcGIS REST services

https://community.esri.com/t5/gis-blog/accessing-arcgis-rest-services-using-r/ba-p/898451

This blog post was also useful, although I couldn’t get the code to work

https://kdvdecisions-blog.netlify.app/2020/04/18/obtaining-spatial-data-from-esri-rest-apis-in-r/

The author suggests that you start by trying out any query first

e.g. check out this page for the 132kV Sub-Tranmission Line(ID:4) service scroll down to the bootom of the page to Supported Operations and click on Query to get following URL

https://services.arcgis.com/bfVzktoY0OhzQCDj/ArcGIS/rest/services/Network_Energex/FeatureServer/4/query

Practice on the REST service here, usually just using Where: & Input Geometry: fields

Note if you just use an Input Geometry, you should make the where clause something like 1 = 1

*** Refactoring to be done

  • when reading via the REST services, the results should be saved using st_write(), instead of saveRDS
  • then when reading back the stored data in this Rmd, use st_read()

Subtransmission - 132kV and 33kV

Also show Zone Substations

Note that it looks like Black Mountain Zone Sub is being bypassed ATM DAPR says upgrade work is in progress Ref (to do)

myOH_132kV <- readRDS(file=paste0(maps_folder,"NoosaOH_132kV.rds"))
# omit next one as "only contains empty units"
myUG_132kV <- readRDS(file=paste0(maps_folder,"NoosaUG_132kV.rds"))
myOH_110kV <- readRDS(file=paste0(maps_folder,"NoosaOH_110kV.rds"))
myUG_110kV <- readRDS(file=paste0(maps_folder,"NoosaUG_110kV.rds"))
myOH_33kV <- readRDS(file=paste0(maps_folder,"NoosaOH_33kV.rds"))
myUG_33kV <- readRDS(file=paste0(maps_folder,"NoosaUG_33kV.rds"))
myZoneSub <- readRDS(file=paste0(maps_folder,"NoosaZoneSub.rds"))

# show feeders individually
tmap_mode(mode = "view")
## tmap mode set to interactive viewing
tm_shape(myOH_132kV) +
  tm_lines(col="red",  lwd = 6) +
  tm_shape(myOH_33kV) +
  tm_lines(col="green",  lwd = 4) +
  tm_shape(myUG_33kV) +
  tm_lines(col="blue",  lwd = 4) +
  tm_shape(myZoneSub) +
  tm_dots(size=0.1, shape=19, title = "ZoneSub")

Now overlay LGA

use tm_borders for this

and note - put any locality layers at the back :-)

Here’s some useful R colours http://www.stat.columbia.edu/~tzheng/files/Rcolor.pdf

myLGA <- readRDS(file=paste0(maps_folder,"Queensland_LGA_map.rds"))

#myLGA <- readRDS(file=paste0(maps_folder,"Queensland_LGA_map.rds"))
# just get Gympie, Noosa & Sunshine Coast
NoosaLGA <- myLGA %>% filter(LGA_CODE %in% c('3620','5740','6720'))

  tm_shape(NoosaLGA) +
  tm_polygons(col = "MAP_COLORS", alpha = 0.2)  +
  tm_shape(myOH_132kV) +
  tm_lines(col="red",  lwd = 6) +
  tm_shape(myOH_33kV) +
  tm_lines(col="green",  lwd = 4) +
  tm_shape(myUG_33kV) +
  tm_lines(col="blue",  lwd = 4) +
  tm_shape(myZoneSub) +
  tm_dots(size=0.1, shape=19, title = "ZoneSub")

Now add 11kV feeders

myOH_11kV <- readRDS(file=paste0(maps_folder,"NoosaOH_11kV.rds"))
myUG_11kV <- readRDS(file=paste0(maps_folder,"NoosaUG_11kV.rds"))

  tm_shape(NoosaLGA)+ 
  tm_polygons(col = "MAP_COLORS", alpha = 0.1) +
  tm_shape(myOH_132kV) +
  tm_lines(col="red",  lwd = 6) +
  tm_shape(myOH_33kV) +
  tm_lines(col="green",  lwd = 4) +
  tm_shape(myUG_33kV) +
  tm_lines(col="blue",  lwd = 4) +
  tm_shape(myZoneSub) +
  tm_dots(size=0.1, shape=19, title = "ZoneSub") +
  tm_shape(myOH_11kV) +
  tm_lines(col="brown",  lwd = 2) +
  tm_shape(myUG_11kV) +
  tm_lines(col="orange",  lwd = 2)

Just DAPR “worst performing feeders”

The Energex DAPR gives a list of worst performaing feeders. Ref: (to do)

The feeders in the Noosa LGA are COR23A, COR25A, BMT5, CRY5A, CRY6A

Click on a feeder to see its name overhead feeders - purple underground - pink

worstOH_11kV <- myOH_11kV %>% filter(FEEDER %in% worst_feeders)
worstUG_11kV <- myUG_11kV %>% filter(FEEDER %in% worst_feeders)

  tm_shape(NoosaLGA) +
  tm_polygons(col = "MAP_COLORS", alpha = 0.1) +
  tm_shape(myOH_132kV) +
  tm_lines(col="red",  lwd = 6) +
  tm_shape(myOH_33kV) +
  tm_lines(col="green",  lwd = 4) +
  tm_shape(myUG_33kV) +
  tm_lines(col="blue",  lwd = 4) +
  tm_shape(myZoneSub) +
  tm_dots(size=0.1, shape=19, title = "ZoneSub") +
  tm_shape(worstOH_11kV) +
  tm_lines(col="purple",  lwd = 2) +
  tm_shape(worstUG_11kV) +
  tm_lines(col="pink",  lwd = 2)

Focus on Cooran feeders for now

Cooran_feeders = c('COR22A','COR23A','COR25A','COR26A')

COR22A_OHfeeder <- myOH_11kV[myOH_11kV$FEEDER=="COR22A",]
COR23A_OHfeeder <- myOH_11kV[myOH_11kV$FEEDER=="COR23A",]
COR25A_OHfeeder <- myOH_11kV[myOH_11kV$FEEDER=="COR25A",]
COR26A_OHfeeder <- myOH_11kV[myOH_11kV$FEEDER=="COR26A",]
COR22A_UGfeeder <- myUG_11kV[myUG_11kV$FEEDER=="COR22A",]
COR23A_UGfeeder <- myUG_11kV[myUG_11kV$FEEDER=="COR23A",]
COR25A_UGfeeder <- myUG_11kV[myUG_11kV$FEEDER=="COR25A",]
COR26A_UGfeeder <- myUG_11kV[myUG_11kV$FEEDER=="COR26A",]

  tm_shape(NoosaLGA) +
  tm_polygons(col = "MAP_COLORS", alpha = 0.1) +
  tm_shape(myOH_132kV) +
  tm_lines(col="red",  lwd = 6) +
  tm_shape(myOH_33kV) +
  tm_lines(col="green",  lwd = 4) +
  tm_shape(myUG_33kV) +
  tm_lines(col="blue",  lwd = 4) +
  tm_shape(myZoneSub) +
  tm_dots(size=0.1, shape=19, title = "ZoneSub") +
  tm_shape(COR22A_OHfeeder) +
  tm_lines(col="cadetblue",  lwd = 2) +
  tm_shape(COR22A_UGfeeder) +
  tm_lines(col="cadetblue3",  lwd = 2) +
  tm_shape(COR23A_OHfeeder) +
  tm_lines(col="chocolate",  lwd = 2) +
  tm_shape(COR23A_UGfeeder) +
  tm_lines(col="chocolate",  lwd = 2) +
  tm_shape(COR25A_OHfeeder) +
  tm_lines(col="deeppink",  lwd = 2) +
  tm_shape(COR25A_UGfeeder) +
  tm_lines(col="deeppink3",  lwd = 2) +
  tm_shape(COR26A_OHfeeder) +
  tm_lines(col="bisque4",  lwd = 2) +
  tm_shape(COR26A_UGfeeder) +
  tm_lines(col="bisque3",  lwd = 2) 

Add postcode overlays

Use the postcode overlays, as we have solar PV capacity data from the Clean Energy Regulator - reported monthly by postcode

Note that the column PC_PID uses a mask QLDxxxx31 where xxxx is the postcode, so 4563 - Cooroy, etc

myPostcodes <- readRDS(file=paste0(maps_folder,"Queensland_Postcode_map.rds"))

NoosaPostcodes <- myPostcodes %>% filter(PC_PID %in% c('QLD456331', 'QLD456531','QLD456631', 'QLD456731','QLD456831', 'QLD456931','QLD457131', 'QLD457331'))

  tm_shape(NoosaLGA)+
  tm_polygons(col = "MAP_COLORS", alpha = 0.1,border.col = "chartreuse") +
  tm_shape(NoosaPostcodes)+
  tm_polygons(col = "MAP_COLORS", alpha = 0.2, border.col = "darkmagenta") +
  tm_shape(myOH_132kV) +
  tm_lines(col="red",  lwd = 6) +
  tm_shape(myOH_33kV) +
  tm_lines(col="green",  lwd = 4) +
  tm_shape(myUG_33kV) +
  tm_lines(col="blue",  lwd = 4) +
  tm_shape(myZoneSub) +
  tm_dots(size=0.1, shape=19, title = "ZoneSub") +
  tm_shape(COR22A_OHfeeder) +
  tm_lines(col="cadetblue",  lwd = 2) +
  tm_shape(COR22A_UGfeeder) +
  tm_lines(col="cadetblue3",  lwd = 2) +
  tm_shape(COR23A_OHfeeder) +
  tm_lines(col="chocolate",  lwd = 2) +
  tm_shape(COR23A_UGfeeder) +
  tm_lines(col="chocolate",  lwd = 2) +
  tm_shape(COR25A_OHfeeder) +
  tm_lines(col="deeppink",  lwd = 2) +
  tm_shape(COR25A_UGfeeder) +
  tm_lines(col="deeppink3",  lwd = 2) +
  tm_shape(COR26A_OHfeeder) +
  tm_lines(col="bisque4",  lwd = 2) +
  tm_shape(COR26A_UGfeeder) +
  tm_lines(col="bisque3",  lwd = 2) 

Postcodes for Cooran Zone Sub feeders

Looks like good correspondance with

4568

4569

4571

  1. Use CER PV data to determine
  1. Use the solar schools api to get PV generation profiles
  1. Add the scaled up local generation estimate to the Zone Sub 30 min load data to get a baseline estimated total consumption. Note this assumes that no generated solar is spilled. Could apply a factor to this……

  2. Then apply an increased “total solar installed in the Zone Sub” catchment. Could project forward to now(today or latest CER) and project forward

  3. Apply the local generation profile from 4. to the baseline in 3. This should give us an implied Zone Sub load for when more solar predicted to be installed. Can then run some basic Zone Sub stats to compare latest with predicted.

  4. Could also work back in years to check historical baseline

Data required

CER data * have this by postcode * smooth from monthly to weekly or daily to reduce chunking

Solar schools api * have running script * have 2020-2021 30 min data for Cooroy State School * check with Dalia if closer schools can be used

Zone Sub load data * have all historic data for all Noosa Zone Subs * have basic analysis scripts

AEMO data * have AEMO data for Queensland as csv * fuel mix (renewable mix) and price - both 30 minute * no scripts run - but easy * could apply to Zone Sub load data to get cost of energy & renewable %age over various time frames (annual, monthly, season, etc)

Now have a go at doing intersects….

This seems to work fine

Postcode_4568 <- myPostcodes %>% filter(PC_PID %in% c('QLD456831'))
  tm_shape(Postcode_4568)+
  tm_polygons(col = "MAP_COLORS", alpha = 0.2, border.col = "darkmagenta")
my_filtered_list <- st_intersects(myOH_11kV, Postcode_4568, sparse = FALSE)
# looks like it returns a vector of what intersects

filtered_myOH_11kV <- myOH_11kV[my_filtered_list, ]

tm_shape(Postcode_4568)+
tm_polygons(col = "MAP_COLORS", alpha = 0.2, border.col = "darkmagenta") +
tm_shape(filtered_myOH_11kV) + tm_lines()

Next try intersects with Cooran feeders

eg st_intersects(substations, Cooran_feeders) st_intersects(LV - OH & UG, Cooran_feeders)

just tried intersect with Postcode_4568 polygon

myOH_LV <- readRDS(file=paste0(maps_folder,"NoosaOH_LV.rds"))
myUG_LV <- readRDS(file=paste0(maps_folder,"NoosaUG_LV.rds"))
mySubstations <- readRDS(file=paste0(maps_folder,"NoosaSubstations.rds"))

# get where substations intersects with COR25A_OHfeeder      

# my_filtered_list <- st_is_within_distance(mySubstations, COR25A_OHfeeder, dist = 10, sparse = FALSE)
my_filtered_list <- st_intersects(myOH_LV, Postcode_4568,sparse = FALSE)

#my_filtered_list <- st_intersects(myOH_LV, COR25A_OHfeeder, sparse = FALSE)
# looks like it returns a vector of what intersects


filtered_myOH_LV <- myOH_LV[my_filtered_list, ]

my_filtered_list <- st_intersects(mySubstations, Postcode_4568,sparse = FALSE)
filtered_mySubstations <- mySubstations[my_filtered_list, ]


tm_shape(Postcode_4568)+
tm_polygons(col = "MAP_COLORS", alpha = 0.2, border.col = "darkmagenta") +
tm_shape(filtered_myOH_11kV) + tm_lines(col="red",lwd=4) +
tm_shape(filtered_myOH_LV) + tm_lines(col="green",lwd=2) +
tm_shape(filtered_mySubstations) + tm_dots(size=0.1)

Next get OHLV that’s close to substations

the following doesn’t return any results for filtered_myOH_LV

# my_filtered_list <- st_is_within_distance(myOH_LV, filtered_mySubstations, dist = 10, sparse = FALSE)
# 
# filtered_myOH_LV <- myOH_LV[my_filtered_list, ]
# 
# tm_shape(Postcode_4568)+
# tm_polygons(col = "MAP_COLORS", alpha = 0.2, border.col = "darkmagenta") +
# tm_shape(COR25A_OHfeeder) + tm_lines(col="red",lwd=4) +
# tm_shape(filtered_myOH_LV) +  tm_lines(col="green",lwd = 2) +
#   tm_shape(filtered_mySubstations) + tm_dots(size=0.1)

more exploring

check out st_join

maybe to combine all the hinterland postcodes - https://www.rdocumentation.org/packages/sf/versions/1.0-3/topics/st_join

could also look at

st_buffer - could add radius to substation points which may help in finding ones that intersect feeders - https://www.postgis.net/docs/ST_Buffer.html

st_buffer & st_intersects work but only for 1st feeder

so try processing one feeder at a time

Best also to combine OH & UG 11kV feeders & same for LV

Note OH & UG have different COLOUR values, so that should differentiate them

Use different line widths for 11kV & LV

buffer <- st_buffer(COR25A_OHfeeder, dist = 40, endCapStyle = "ROUND", nQuadSegs = 20 )

my_filtered_list <- st_intersects(myOH_LV, buffer,sparse = FALSE)
filtered_myOH_LV <- myOH_LV[my_filtered_list, ]

my_filtered_list <- st_intersects(mySubstations, buffer,sparse = FALSE)
filtered_mySubstations <- mySubstations[my_filtered_list, ]

tm_shape(buffer)+
tm_polygons(col = "MAP_COLORS", alpha = 0.2, border.col = "darkmagenta")+
tm_shape(COR25A_OHfeeder) + tm_lines(col="red",lwd=6) +
tm_shape(filtered_myOH_LV) + tm_lines(col="green",lwd=2) +
tm_shape(filtered_mySubstations) + tm_dots(size=0.1)
# Looks like this worked for the first feeder in the list
# So should process feeder by feeder........

General case for 11kV feeder pair(OH & UG)

  • create a composite of OH & UG line segments
  • create an enclosing polygon by forming a buffer around the lines
  • find OH LV lines that intersects
  • find UG LV lines that intersects
  • find substations that intersects
  • plot in order ** locality if required (LGA/postcode) ** buffer zone ** 11kV feeders - separately OH & UG - different colours, lwd=8 to stand out ** LV feeders - separately OH & UG - different colours, lwd=2 ** substations
COR25A <- rbind(COR25A_OHfeeder,COR25A_UGfeeder, deparse.level = 0)
buffer <- st_buffer(COR25A, dist = 40, endCapStyle = "ROUND", nQuadSegs = 20 )

my_filtered_list <- st_intersects(myOH_LV, buffer,sparse = FALSE)
filtered_myOH_LV <- myOH_LV[my_filtered_list, ]
my_filtered_list <- st_intersects(myUG_LV, buffer,sparse = FALSE)
filtered_myUG_LV <- myUG_LV[my_filtered_list, ]
#filtered_myLV <- rbind(filtered_myOH_LV, filtered_myUG_LV, deparse.level = 0)

my_filtered_list <- st_intersects(mySubstations, buffer,sparse = FALSE)
filtered_mySubstations <- mySubstations[my_filtered_list, ]

tm_shape(buffer)+
tm_polygons(col = "MAP_COLORS", alpha = 0.2, border.col = "darkmagenta") +
tm_shape(COR25A_OHfeeder) + tm_lines(col='pink', lwd=8) +
  tm_shape(COR25A_UGfeeder) + tm_lines(col='red',lwd=8) +
  tm_shape(filtered_myOH_LV) + tm_lines(col='green',lwd=2) +
  tm_shape(filtered_myUG_LV) +tm_lines(col='blue', lwd=2) +
  tm_shape(filtered_mySubstations) + tm_dots(size=0.1)
## Warning: The shape filtered_myOH_LV contains empty units.
## Warning: The shape filtered_myUG_LV contains empty units.