@@ -520,377 +520,7 @@ def getSoilGrid(centroid, latlong_crs, custom_crs, soil_file, nrows=100, ncols=1
520520
521521
522522
523- def plot3d (lease_xs , lease_ys , bathymetryfilename , area_on_bath = False , args_bath = {}, xbounds = None , ybounds = None , zbounds = None ):
524- '''Plot aspects of the Project object in matplotlib in 3D'''
525-
526- # organize the bathymetry arguments
527- if len (args_bath )== 0 :
528- args_bath = {'zlim' :[- 3200 ,500 ], 'cmap' :'gist_earth' }
529-
530- fig = plt .figure (figsize = (6 ,4 ))
531- ax = plt .axes (projection = '3d' )
532-
533- if xbounds != None :
534- ax .set_xlim (xbounds [0 ], xbounds [1 ])
535- if ybounds != None :
536- ax .set_ylim (ybounds [0 ], ybounds [1 ])
537- if zbounds != None :
538- ax .set_zlim (zbounds [0 ], zbounds [1 ])
539-
540- # plot the lease area in a red color, if desired
541- ax .plot (lease_xs , lease_ys , np .zeros (len (lease_xs )), color = 'r' , zorder = 100 )
542-
543- # plot the bathymetry in matplotlib using a plot_surface
544-
545- # !!!! include option to plot entire bathymetry file or not
546-
547- if isinstance (bathymetryfilename , str ):
548- bathGrid_Xs , bathGrid_Ys , bathGrid = sbt .readBathymetryFile (bathymetryfilename ) # parse through the MoorDyn/MoorPy-formatted bathymetry file
549- X , Y = np .meshgrid (bathGrid_Xs , bathGrid_Ys ) # create a 2D mesh of the x and y values
550- bath = ax .plot_surface (X , Y , - bathGrid , rstride = 1 , cstride = 1 ,
551- vmin = args_bath ['zlim' ][0 ], vmax = args_bath ['zlim' ][1 ],
552- cmap = args_bath ['cmap' ])
553-
554- '''
555- # plot the project boundary
556- if boundary:
557- ax.plot(self.boundaryXs, self.boundaryYs, np.zeros(len(self.boundaryXs)), color='b', zorder=100, alpha=0.5)
558- '''
559-
560- # plot the projection of the lease area bounds on the seabed, if desired
561- if area_on_bath :
562- lease_zs = projectAlongSeabed (lease_xs , lease_ys , bathGrid_Xs , bathGrid_Ys , bathGrid )
563- ax .plot (lease_xs , lease_ys , - lease_zs , color = 'tab:blue' , zorder = 10 , alpha = 0.5 )
564-
565-
566- set_axes_equal (ax )
567- ax .axis ('off' )
568-
569- return fig , ax
570-
571-
572-
573- def projectAlongSeabed (x , y , bathXs , bathYs , bath_depths ):
574- '''Project a set of x-y coordinates along a seabed surface (grid),
575- returning the corresponding z coordinates.'''
576-
577- if len (x ) == len (y ):
578- n = len (x )
579- z = np .zeros (n ) # z coordinate of each point [m]
580- a = np .zeros (n ) # could also do slope (dz/dh)
581- for i in range (n ):
582- z [i ], nvec = sbt .getDepthFromBathymetry (x [i ], y [i ], bathXs , bathYs , bath_depths )
583-
584- else :
585- z = np .zeros ([len (y ), len (x )])
586- for i in range (len (y )):
587- for j in range (len (x )):
588- z [i ,j ], nvec = sbt .getDepthFromBathymetry (x [j ], y [i ], bathXs_mesh , bathYs_mesh , bath_depths )
589-
590- return z
591-
592-
593-
594-
595-
596-
597-
598-
599-
600-
601-
602- """
603- if self.lat0 != 0 and self.lon0 != 0:
604- # set the centroid of the project and save in a GeoDataFrame
605- self.centroid = (self.lon0, self.lat0)
606- self.gdf = gpd.GeoDataFrame({'type':'centroid', 'geometry': [Point(self.centroid)]}, crs=self.latlong_crs)
607- # set the target coordinate reference system (CRS) that will switch between regular lat/long system and "meters from centroid" system, based on centroid location
608- information
609- # extract the numeric code
610- self. # save the target CRS (UTM 10N = 32610)
611-
612-
613- gdf_leases = gpd.GeoDataFrame({'type': 'lease_area', 'geometry': lease_area.geometry}, crs=getLatLongCRS() )
614-
615- gdf = add2geodataframe(gdf0, gdf_leases)
616-
617- # convert lat/long boundary/lease area points to meters away from the centroid
618- self.lease_xs, self.lease_ys = self.convertLatLong2Meters(self.area_longs, self.area_lats, self.centroid)
619-
620-
621- if which_centroid=='lease_area':
622- # make a blank copy of the gdf to switch to the target CRS to get the accurate centroid
623- gdf_utm = self.gdf.copy().to_crs(self.target_crs)
624- centroid_utm = (gdf_utm.geometry.centroid.values.x[0], gdf_utm.geometry.centroid.values.y[0])
625- gdf_centroid = gpd.GeoDataFrame({'type':'centroid', 'geometry': [Point(centroid_utm)]}, crs=self.target_crs)
626- else:
627- # assuming the input centroid is in a long/lat pair
628- gdf_centroid = gpd.GeoDataFrame({'type':'centroid', 'geometry': [Point(which_centroid)]}, crs=self.latlong_crs)
629- gdf_centroid.to_crs(self.target_crs)
630-
631- self.centroid_utm = (gdf_centroid.geometry.values.x[0], gdf_centroid.geometry.values.y[0])
632- self.centroid = (gdf_centroid.to_crs(self.latlong_crs).geometry.values.x[0], gdf_centroid.to_crs(self.latlong_crs).geometry.values.y[0]) # assume centroid is focal point of Project
633-
634- def initialize_geodataframe(crs, columns=['type','geometry']):
635-
636- gdf = gpd.GeoDataFrame(columns=columns, geometry='initialization', crs=crs)
637-
638- return gdf
639-
640- def add2geodataframe(gdf_to_add_to, gdf_to_add):
641-
642- # check to make sure they have the same columns and CRS
643-
644- gdf_new = pd.concat([gdf_to_add_to, gdf_to_add])
645-
646- return gdf_new
647-
648-
649-
650-
651-
652- # TODO
653-
654- # reference entire CA bathymetry file (maybe)
655- # plot2d method and a plotGDF method (with bathymetry in the geodataframe using contours)
656-
657- # add the coastline
658- #xcoast, ycoast = sbt.getCoast(self.Xs, self.Ys, self.depths)
659- #ax.plot(xcoast, ycoast, np.zeros(len(self.Ys)), color='k', zorder=100)
660-
661- # need to fix up bounds
662- #xbmin, xbmax = sbt.getPlotBounds(self.longs_bath, self.centroid, long=True)
663- #ybmin, ybmax = sbt.getPlotBounds(self.lats_bath, self.centroid, long=False)
664-
665- plt.show()
666-
667-
668-
669-
670-
671-
672-
673-
674- # METHODS USED SPECIFICALLY FOR DEEPFARM LCOE ANALYSIS
675-
676- def addMap2GDF(self, filename='', states=None):
677- '''function to include a shapefile of a provided map'''
678-
679- # read in the provided filename to add to the geodataframe
680- usa = gpd.read_file(filename)
681- # internal list of states, in order, to go with the default U.S. states shapefile
682- statenamelist = ['Maryland','Iowa','Delaware','Ohio','Pennsylvania','Nebraska','Washington','Puerto Rico','Alabama','Arkansas','New Mexico', # 0-10
683- 'Texas','California','Kentucky','Georgia','Wisconsin','Oregon','Missouri','Virginia','Tennessee','Louisiana','New York', # 11-21
684- 'Michigan','Idaho','Florida','Alaska','Illinois','Montana','Minnesota','Indiana','Massachusetts','Kansas','Nevada','Vermont', # 22-33
685- 'Connecticut','New Jersey','Washington D.C.','North Carolina','Utah','North Dakota','South Carolina','Mississippi','Colorado', # 34-42
686- 'South Dakota','Oklahoma','Wyoming','West Virginia','Maine','Hawaii','New Hampshire','Arizona','Rhode Island'] # 43-51
687- # insert names of the states into the new gdf
688- usa.insert(0, 'type', statenamelist)
689- # set the CRS of the USA pdf to the right CRS
690- usa.set_crs(crs="EPSG:4326", inplace=True)
691- self.usa = usa
692-
693- for state in states:
694- state_gs = usa.loc[usa['type']==state]
695- self.gdf = pd.concat([self.gdf, state_gs])
696-
697-
698-
699- def setFarmLayout(self, style='grid', nrows=10, ncols=10, turbine_spacing=2000, nOSS=2):
700-
701- if style=='grid':
702- # for now, this is very custom code specific to the DeepFarm project
703- farmxspacing = (nrows-1)*turbine_spacing
704- farmyspacing = (ncols-1)*turbine_spacing
705-
706- turbine_distances_from_centroid = []
707- oss_distances_from_centroid = []
708- for j in reversed(range(ncols)):
709- for i in range(nrows):
710- xpos = -(farmxspacing/2)+(i*turbine_spacing)
711- ypos = -(farmyspacing/2)+(j*turbine_spacing)
712- turbine_distances_from_centroid.append((xpos, ypos))
713-
714- # add positions of two offshore substations (OSSs)
715- oss_distances_from_centroid.append((11000.0, 5000.0))
716- oss_distances_from_centroid.append((11000.0, -5000.0))
717-
718- if style=='shared':
719- turbine_xspacing = np.sqrt(2000**2-1000**2)
720- turbine_yspacing = 2000
721- farmxspacing = turbine_xspacing*9
722- farmyspacing = turbine_yspacing*9
723-
724- turbine_distances_from_centroid = []
725- oss_distances_from_centroid = []
726- for j in reversed(range(ncols)):
727- for i in range(nrows):
728- xpos = -(farmxspacing/2)+(i*turbine_xspacing)
729- ypos = -(farmyspacing/2)+(j*turbine_yspacing) - 1000*np.sin(np.radians(30)) + 1000*(i%2)
730- turbine_distances_from_centroid.append((xpos, ypos))
731-
732- # add positions of two offshore substations (OSSs)
733- oss_distances_from_centroid.append((5.5*turbine_xspacing, 2.0*turbine_yspacing+1000*np.sin(np.radians(30))))
734- oss_distances_from_centroid.append((5.5*turbine_xspacing, -2.5*turbine_yspacing-1000*np.sin(np.radians(30))))
735-
736- if style=='small-shared':
737- turbine_xspacing = np.sqrt(2000**2-1000**2)
738- turbine_yspacing = 2000
739- farmxspacing = turbine_xspacing*1
740- farmyspacing = turbine_yspacing*2
741-
742- turbine_distances_from_centroid = []
743- oss_distances_from_centroid = []
744- for j in reversed(range(3)):
745- for i in range(2):
746- xpos = -(farmxspacing/2)+(i*turbine_xspacing)
747- ypos = -(farmyspacing/2)+(j*turbine_yspacing) - 1000*np.sin(np.radians(30)) + 1000*(i%2)
748- turbine_distances_from_centroid.append((xpos, ypos))
749-
750- # add positions of two offshore substations (OSSs)
751- oss_distances_from_centroid.append((-0.5*turbine_xspacing, 2.0*turbine_yspacing-1000*np.sin(np.radians(30))))
752-
753-
754- # create a copy of the global gdf and transform it into the easting/northing coordinate reference system
755- gdf_utm = self.gdf.copy().to_crs(self.target_crs)
756- xcentroid = gdf_utm.loc[gdf_utm['type']=='centroid'].centroid.x[0]
757- ycentroid = gdf_utm.loc[gdf_utm['type']=='centroid'].centroid.y[0]
758-
759- # create shapely Point objects of the turbine positions relative to the centroid, in the UTM CRS
760- turbine_geoms = []
761- for i,(x,y) in enumerate(turbine_distances_from_centroid):
762- turbine_geoms.append( Point(xcentroid + x, ycentroid + y) )
763-
764- oss_geoms = []
765- for i,(x,y) in enumerate(oss_distances_from_centroid):
766- oss_geoms.append( Point(xcentroid + x, ycentroid + y) )
767-
768- # make a new gdf to put the turbine data together
769- turbine_gdf = gpd.GeoDataFrame({'type': ['turbine']*len(turbine_geoms), 'geometry': turbine_geoms}, crs=self.target_crs)
770- # make a new gdf to put the substation data together
771- oss_gdf = gpd.GeoDataFrame({'type': 'substation', 'geometry': oss_geoms}, crs=self.target_crs)
772- # merge these two geodataframes together into one (best way I can find to "add" rows to a dataframe; ignoring index makes all indices a different number)
773- turbine_gdf = pd.concat([turbine_gdf, oss_gdf], ignore_index=True)
774-
775- # convert the turbine/oss coordinates back to regular latitude/longitude (EPSG: 4326)
776- turbine_gdf = turbine_gdf.to_crs('EPSG:4326')
777-
778- # add the turbine gdf to the global gdf
779- self.gdf = pd.concat([self.gdf, turbine_gdf], ignore_index=True)
780-
781- # add local variables in this method to the turbine_gdf to be used later (but don't need for the global gdf)
782- turbine_gdf.insert(2, 'easting_northing_geometry', turbine_geoms + oss_geoms)
783- turbine_gdf.insert(3, 'meters_from_centroid', turbine_distances_from_centroid + oss_distances_from_centroid)
784-
785- # save this new turbine_gdf for future use
786- self.turbine_gdf = turbine_gdf
787-
788- # make a layout CSV (used for WHaLE/WAVES)
789- self.makeLayoutCSV()
790-
791-
792-
793- def makeLayoutCSV(self, filename='layout_test.csv'):
794-
795- turbine_longs = [point.coords[0][0] for point in self.turbine_gdf.geometry]
796- turbine_lats = [point.coords[0][1] for point in self.turbine_gdf.geometry]
797-
798- self.turbine_gdf.insert(2, 'longitude', turbine_longs)
799- self.turbine_gdf.insert(3, 'latitude', turbine_lats)
800-
801- turbine_eastings = [point.coords[0][0] for point in self.turbine_gdf['easting_northing_geometry']]
802- turbine_northings = [point.coords[0][1] for point in self.turbine_gdf['easting_northing_geometry']]
803-
804- #self.turbine_gdf.insert(5, 'easting', turbine_eastings)
805- #self.turbine_gdf.insert(6, 'northing', turbine_northings)
806-
807- turbine_x_from_centroid = [point[0] for point in self.turbine_gdf['meters_from_centroid']]
808- turbine_y_from_centroid = [point[1] for point in self.turbine_gdf['meters_from_centroid']]
809-
810- self.turbine_gdf.insert(5, 'easting', turbine_x_from_centroid)
811- self.turbine_gdf.insert(6, 'northing', turbine_y_from_centroid)
812-
813- self.turbine_gdf.insert(8, 'floris_x', turbine_x_from_centroid)
814- self.turbine_gdf.insert(9, 'floris_y', turbine_y_from_centroid)
815-
816- columns = ['type', 'longitude', 'latitude', 'easting', 'northing', 'floris_x', 'floris_y']
817- df = pd.DataFrame(self.turbine_gdf)
818- df.to_csv(filename, columns=columns)
819-
820-
821- def plotGDF(self, kwargs):
822- '''2D map-like plot'''
823-
824- if 'centroid' in kwargs:
825- centroid_settings = kwargs['centroid']
826- if 'label' in centroid_settings:
827- centroid_label = 'centroid'
828- if 'map' in kwargs:
829- map_settings = kwargs['map']
830- if 'farm' in kwargs:
831- farm_settings = kwargs['farm']
832-
833- fig, ax = plt.subplots(1,1)
834-
835- if 'centroid' in kwargs:
836- self.gdf.loc[self.gdf['type']=='centroid'].plot(ax=ax, color=centroid_settings['color'], label=centroid_label)
837-
838- if 'boundary' in kwargs:
839- map_boundary = self.gdf.loc[self.gdf['type']=='California'].boundary
840- map_boundary.plot(ax=ax, color=map_settings['color'])
841-
842- if 'farm' in kwargs:
843- self.gdf.loc[self.gdf['type']=='turbine'].plot(ax=ax, color=farm_settings['turbine']['color'], label='turbine')
844- self.gdf.loc[self.gdf['type']=='substation'].plot(ax=ax, color=farm_settings['oss']['color'], label='substation')
845-
846- ax.set_xlabel('Longitude')
847- ax.set_ylabel('Latitude')
848- ax.legend()
849-
850- ax.set_xlim([-124.875, -124.55])
851- ax.set_ylim([40.025, 40.25])
852-
853- fig.tight_layout()
854-
855- # Some GeoPandas Help
856- # to plot just one entry of a geoseries: gdf.loc[[0],'geometry'].plot()
857- # to get the columns of a gdf: gdf.columns
858- # merging gdf's
859- # adding columns to gdf's
860-
861- return fig, ax
862-
863-
864-
865- def addPoints(self, ax, pointlist=[], kwargs={}):
866-
867- point_settings = kwargs['pointlist']
868-
869- points = gpd.GeoDataFrame({'type':['nrel_channel','nrel_humboldt','nrel_crescent_city','hawaii'],
870- 'geometry': pointlist}, crs='EPSG:4326')
871-
872- points.plot(ax=ax, color=point_settings['color'], marker=point_settings['marker'], label=point_settings['label'])
873-
874-
875- def addState(self, ax, states=[], kwargs={}):
876-
877- for state in states:
878- state_settings=kwargs[state]
879-
880- state_geom = self.usa.loc[self.usa['type']==state]
881- if 'boundary' in state_settings:
882- state_geom = state_geom.boundary
883-
884- newstate = gpd.GeoDataFrame({'type':state, 'geometry':state_geom}, crs='EPSG:4326')
885-
886- newstate.plot(ax=ax, color=state_settings['color'])
887-
888-
889-
890-
891-
892523
893- """
894524
895525
896526
0 commit comments