Release Notes
Changelog
All major changes are listed here.
1.0.2 (2025-07-21)
WindKit 1.0.2 is a patch release to ensure consistent config and app data paths on windows. Both the config and app data paths are now set by default to C:\\Users\\<user>\\AppData\\Roaming\\DTU Wind Energy\\windkit.
1.0.1 (2025-07-15)
WindKit 1.0.1 is a patch release that changes the config migration that shipped with 1.0.0. The changed ensures that the legacy .ini configuration files are migrated to the new .toml format without automatically removing the old file. This ensures that users are not constantly prompted to update their configuration file if they use different versions of WindKit in different environments.
1.0.0 (2025-06-26)
This is a major release that introduces a significantly cleaner and more intuitive API. We have removed many functions from the public namespace, renamed others for consistency, and introduced powerful new features. While this version includes many breaking changes, the result is a more streamlined and user-friendly library. We strongly recommend all users to carefully read these release notes and update their code.
Highlights
Simplified and Consistent API
The windkit namespace has been significantly cleaned up to make the API more predictable and easier to learn. Many internal or redundant functions have been removed from the public API, and others have been renamed for better clarity and consistency.
Functions for reading and writing different objects in windkit are now grouped by type, such as
read_tswc,read_bwc,read_wwc, andread_gwcfor reading wind climate datasets, andbwc_to_file,wwc_to_file, andgwc_to_filefor writing them.Functions for creating empty datasets are now prefixed with
create_*(e.g.,create_bwcinstead ofempty_bwc).Functions for creating wind climate objects from other data types now follow a
[climate]_from_[source]pattern (e.g.,bwc_from_tswcinstead ofbwc_from_timeseries).Validation functions are now consistently named
validate_*(e.g.,validate_bwcinstead ofbwc_validate).
Revamped Map Reading and Writing
The API for handling spatial maps has been completely overhauled. The generic read_raster_map, read_vector_map, raster_map_to_file, and vector_map_to_file functions have been replaced by specific, format-aware functions for each map type:
read_elevation_mapandelevation_map_to_fileread_roughness_mapandroughness_map_to_fileread_landcover_mapandlandcover_map_to_file
These new functions automatically infer the file format from the suffix (e.g., .map, .tif, .gpkg) and provide a more robust and intuitive interface for working with elevation, roughness, and landcover data.
Polygon Representation for Landcover and Roughness Maps
A major improvement is the new default support for polygon-based landcover and roughness maps. The functions read_landcover_map and read_roughness_map now return geopandas.GeoDataFrame objects with polygons when reading vector data, which is a more standard and powerful representation for GIS data. This enables more robust handling and validation of maps. For backward compatibility, you can still work with the legacy line-based format by setting polygons=False.
Unified API for Wind Climate Statistics
Calculating statistics from wind climate objects is now much simpler. A new set of generic functions can operate on any wind climate type (BWC, WWC, etc.):
wk.mean_wind_speedwk.mean_power_densitywk.ws_cdf(Cumulative Distribution Function)wk.ws_freq_gt_meanwk.mean_ws_moment
This unified API replaces the climate-specific functions (e.g., bwc_mean_windspeed), simplifying your code and making it more versatile.
New Loss and Uncertainty Modeling
WindKit now includes tools to support loss and uncertainty analysis, designed to integrate seamlessly with PyWAsP. You can now create, validate, and summarize standardized loss and uncertainty tables using:
get_loss_table,total_loss,loss_summaryget_uncertainty_table,total_uncertainty,uncertainty_summary
This provides a structured framework for AEP calculations.
Breaking Changes and Migration Guide
Due to the extensive API changes, you will need to update your existing code. Here is a guide to the most common changes:
General Renaming and Removals
Namespace Cleanup: Many functions like
bwc_validate_wrapper,update_history, and variousspatialutilities have been removed from the publicwindkitnamespace.Function Renaming:
windkit.read_timeseries_from_pandasis nowwindkit.tswc_from_dataframe.windkit.bwc_from_timeseriesis nowwindkit.bwc_from_tswc.windkit.read_timeseries_from_csvis nowwindkit.read_tswc.All
windkit.empty_*functions are nowwindkit.create_*(e.g.,empty_bwc->create_bwc).lines2polyis nowlines_to_poly, andpoly2linesis nowpoly_to_lines.add_crsis nowset_crs.Argument Renaming: Several function arguments have been renamed for consistency. For example,
nsecis nown_sectorsandnwsbinsis nown_wsbins. Check the function signatures if you encounter errors.Removed Classes: The
windkit.WindTurbinesclass has been removed. Use the functions in thewindkit.wind_turbinesmodule to work withxarray.Datasetrepresentations of turbines.
Wind Climate I/O
Wind climate reading and writing has been standardized to one reader and one writer for each type:
Use
read_tswcto read time series wind climate datasets.Use
read_bwcandbwc_to_filefor Binned Wind Climate datasets.Use
read_wwcandwwc_to_filefor Weibull Wind Climate datasets.Use
read_gwcandgwc_to_filefor Generalized Wind Climate datasets.
Configuration File and Environment Variables
The configuration file format has been switched from INI to TOML. Existing .ini configuration files will be migrated automatically.
Additionally, user details can now be configured using case-insensitive environment variables, which is ideal for containerized or CI/CD environments:
WINDKIT_NAMEWINDKIT_EMAILWINDKIT_INSTITUTION
If no configuration is found (either via file or environment variables), you will be prompted for the information upon initialization.
Full list of changes
Bug Fixes
clip_with_marginnow returns aValueErrorwhen the bbox crosses the dateline.Fixed an issue where
read_raster_mapwas checking for too high roughness values twice.Duplicate heights passed to
create_datasetwithstruct=stacked_pointare now correctly removed.gdf_to_dsnow correctly handles unique points to ensure round-tripping withds_to_gdfworks as expected.Fixed a bug where
get_vector_mapfor CORINE data could fail with a missing column error.to_stacked_pointnow correctly retains the input order of coordinates.nearest_pointsnow raises an error on duplicate points to be compatible with newer xarray versions.Fixed a bug in
wk.spatial.add_crswhere custom projection information could be overwritten by a detected EPSG code.Fixed
wk.spatial.interp_unstructured_liketo correctly broadcast single-point sources.Fixed a bug in
nearest_pointswhenkeep_duplicates=Falseandreturn_distance=True.
API Breaks
windkit.read_timeseries_from_pandasrenamed aswindkit.tswc_from_dataframewindkit.bwc_from_timeseriesrenamed aswindkit.bwc_from_tswcwindkit.read_timeseries_from_csvrenamed aswindkit.read_tswcall
windkit.empty_*functions renamed towindkit.create_*renamed
lines2polytolines_to_polyandpoly2linestopoly_to_linesremoved
wk.lib_stringfrom public namespacewindkit.spatial.interp_unstructured_likeandwindkit.spatial.interp_structured_likewill not interpolate over 1D variables by defaultRemoved
read_raster_map,raster_map_to_file, andread_vector_mapandvector_map_to_file(made private)Added
read_elevation_mapandelevation_map_to_file(works for vector and raster)Added
read_roughness_mapandroughness_map_to_file(works for vector and raster)Added
read_landcover_map, andlandcover_map_to_file(works for vector and raster)Old .gpkg files with change lines in landcover_map_to_file and roughness_map_to_file can be written by using polygons=False
File formats for the readers and writers described above are now inferred from the filename’s suffix, e.g.,
.mapfor map files.The functions
read_landcover_mapandread_roughness_mapby default return polygons instead of changes lines. You can set the argumentpolygons=Falseto open the file as old fashioned change lines. You can try this if your file is not being opened correctly, but you are responsible for checking it’s correctness, because there is less error checking for these types of files.Added
roughness_to_landcoverto convert roughness maps to landcover maps (vector or raster)Added
landcover_to_roughnessto convert landcover maps to roughness maps (vector or raster)Renamed
add_crstoset_crsand and deprecatedadd_crs(which callsset_crs)get_vector_mapnow returns landcover data as polygons by default.Removed
wk.bwc_ws_momentfrom public namespace, usewk.mean_ws_momentinsteadRemoved
wk.bwc_mean_windspeedfrom public namespace, usewk.mean_wind_speedinsteadRemoved
wk.bwc_mean_windspeed3from public namespace, usewk.mean_wind_speed3insteadRemoved
wk.bwc_power_densityfrom public namespace, usewk.mean_power_densityinsteadRemoved
wk.bwc_ws_cdffrom public namespace, usewk.ws_cdfinsteadRemoved
wk.bwc_ws_freq_gt_meanfrom public namespace, usewk.ws_freq_gt_meaninsteadRemoved
wk.bwc_to_tabfilefrom public namespace, usewk.bwc_to_fileinsteadRemoved
wk.bwc_validate_wrapperfrom public namespaceRemoved
wk.create_time_attributesfrom public namespaceRemoved
wk.count_to_ws_freq_by_sectorfrom public namespaceRemoved
wk.read_rsffilefrom public namespace usewk.read_wwcinsteadRemoved
wk.read_wrgfilefrom public namespace, usewk.read_wwcinsteadRemoved
wk.read_grdfilefrom public namespace, usewk.read_wwcinsteadRemoved
wk.read_pwcfilefrom public namespace, usewk.read_wwcinsteadRemoved
wk.to_rsffilefrom public namespace, usewk.wwc_to_fileinsteadRemoved
wk.to_wrgfilefrom public namespace, usewk.wwc_to_fileinsteadRemoved
wk.wwc_validate_wrapperfrom public namespaceRemoved
wk.wwc_validate_structureRemoved
wk.wwc_validate_structure_wrapperRemoved
wk.wwc_mean_windspeedfrom public namespace, usewk.mean_wind_speedinsteadRemoved
wk.wwc_power_densityfrom public namespace, usewk.mean_power_densityinsteadRemoved
wk.to_libfilefrom public namespace, usewk.gwc_to_fileinsteadRemoved
wk.gwc_validate_wrapperfrom public namespaceRemoved
wk.wtg_validate_wrapperfrom public namespaceRemoved
wk.windturbines_validate_wrapperfrom public namespaceModified
wk.read_tswcto be a generic tswc reader (not just for CSV)Renamed
wk.is_windturbinestowk.is_wind_turbinesRenamed
wk.windturbines_validatetowk.validate_windturbinesRenamed
wk.wtg_validatetowk.validate_wtgRenamed
wk.gwc_validatetowk.validate_gwcRenamed
wk.wwc_validatetovalidate_wwcRenamed
wk.bwc_validatetowk.validate_bwcRemoved
wk.get_mapRemoved
wk.spatial.interpolate_to_gridRemoved
wk.WindTurbinesRemoved
wk.Workspace.get_vector_mapAdded
wk.Workspace.get_elevation_mapAdded
wk.Workspace.get_roughness_mapRemoved
wk.bwc_from_counts(from public namespace)Removed
wk.create_wv_count(from public namespace)Removed
wk.update_history(from public namespace)Removed
wk.update_coords_attrs(from public namespace)Removed
wk.update_var_attrs(from public namespace)Removed
wk.ALL_VARS_META(from public namespace)Removed
wk.spatial.spatial_stack(from public namespace)Removed
wk.spatial.spatial_unstack(from public namespace)Removed
wk.spatial.stack_then_unstack(from public namespace)Removed
wk.spatial.get_latitude(from public namespace)Removed
wk.spatial.is_vertical(from public namespace)Removed
wk.import_optional_dependency(from public namespace)Removed
wk.reproject_gwc(from public namespace)Removed
wk.get_ee_map(from public namespace)Removed
wk.create_coordsRenamed
wk.create_ws_bin_coordstowk.create_wsbin_coordsand changed the arguments tobins,widthandstart.binsis an integer number of bins or a list of bin edges.widthis the width of the bins, andstartis the starting point of the first bin.widthandstartare only used ifbinsis an integer.Removed
wk.create_ws_bin_coords_from_valuesChanged
wk.create_sector_coordsarguments tobinsandstart.binsis an integer number of bins or a list of bin edges.startis the starting point of the first bin. By default,startis -360/n_bins/2.Removed
wk.create_sector_coords_from_edgesRemoved
wk.create_direction_coords(from public namespace)wk.create_vector_mapnow has bbox as a first positional argument and argumentdistis removedRenamed
wk.get_land_cover_tabletowk.get_landcover_table
New features
wk.read_wtgcan read wind turbine generators files in netCDF format.wk.mean_ws_momentto calculate the mean of a wind speed moment of any wind climatewk.ws_cdfto calculate the cumulative distribution function of a wind speed of any wind climatewk.ws_freq_gt_meanto calculate the fraction of probability mass above the mean of a wind speed of any wind climatewk.mean_wind_speedto calculate the mean wind speed of any wind climatewk.mean_wind_speed3to calculate the mean wind speed cubed of any wind climatewk.mean_power_densityto calculate the mean power density of any wind climateAll of the above calculates the the variable of all wind climates (not all functions are supports all climates yet).
Added
read_wwcto read a weibull wind climate dataset from a fileAdded
read_mfwwcto read a multi-filey weibull wind climate datasetAdded
wwc_to_fileto write a weibull wind climate dataset to a fileAdded
read_gwcto read a generalized wind climate dataset from a fileAdded
gwc_to_fileto write a generalized wind climate dataset to a fileAdded
bwc_to_fileto write a binned wind climate dataset to a fileNew function
add_projected_wrf_coordinatesthat is useful to processWRFoutput data to be used withwindkit.Existing function
windkit.read_wtgcan optionally read the wind turbine manufacturer name from a.wtgfile if exists.New function
windkit.metadata.update_coords_attrsto update attributes of a dataset coordinates.New function
create_baroto create a baro file with dummy valuesNew function
create_stabto create a stab file with dummy valuesNew function
windkit.snap_to_layerthat transform a vector map with polyons with gaps, open areas and inconsistent vertices into a valid vector map to runpywasp.New example notebook tutorial for
windkit.get_era5to get ERA5 data from Microsoft Planetary Computerwindkit.raster_map_to_fileallows extra arguments that are forwarded torasterio.open. Useful to create e.g. compressed geoTIFF files with the “compress” option.New class
windkit.WengWorkspaceto read WAsP Engineering proyect files in XML format and converting its content toxarray.Datasetandxarray.DataArrayinstances such as extreme wind climate datasets, location datasets and raster map data arrays.Enable roughness maps to be written to
.mapfilesAdded kw-argument
return_lctableto functions reading landcover maps, set to false by default, which means only the landcover map is returnedAdded kw-argument
convert_to_landcoverto functions reading roughness maps to optionally convert the map to landcover, returning both the map and the table (two outputs)It is now allowed to use
wk.landcover_map_to_fileto write a landcover map to a.mapfile as long as the displacements are all zero.lines_to_polygonsis a more robust version oflines_to_polyand now tries to make the polygons valid if they are not. It is also much faster.polygons_to_linesis a more robust version ofpoly_to_linesand is much faster.Added function
windkit.plot.landcover_map, which can plot a landcover map with some nicer color schemes.Added function
windkit.plot.elevation_map, which can plot an elevation map with some nicer color schemes.Added function
windkit.add_landcover_tableto add roughness and other information from a wk.LandCoverTable to a geopandas dataframe with only anidcolumnin
get_raster_map, an option to download from GWA4 landcoverGWA4_landcoverandGWA4_elevationhas been addedAdded function
windkit.get_tutorial_datato download tutorial data from the windkit zenodo repository. The data is downloaded to a local cache directory, which is created if it does not exist.Configuration can now be defined using case-insensitive environment variables
windkit_name,windkit_emailandwindkit_institution. If these are not set, and the configuration file is not found, you will be prompted on initialization.
Added functionality to work with losses
Defined the data structure of loss tables: a pandas DataFrame with required columns: “loss_name” and “loss_percentage”. It can also have optional columns “loss_category”, “loss_upper_bound”, “loss_lower_bound”, “loss_default”, and “description”
Added function
get_loss_tableto obtain a loss tables (DataFrame) from known name. Currently, only “dtu_default” exists.Added function
validate_loss_tableto validate a loss table is formatted correctlyAdded function
total_lossto calculate the total loss in percentage from a loss tableAdded function
loss_summaryto print a formatted summary of the loss tableAdded function
total_loss_factorto calculate the loss factor (the factor that can be directly multiplied to subtract the loss from an AEP number)
Added functionality to work with uncertainties
Defined the data structure of uncertainty tables: a pandas DataFrame with required columns: “uncertainty_kind”, “uncertainty_name” and “uncertainty_percentage”. It can also have optional columns “uncertainty_category”, “uncertainty_upper_bound”, “uncertainty_lower_bound”, “uncertainty_default”, and “description”
Added function
get_uncertainty_tableto obtain an uncertainty table (DataFrame) from known name. Currently, only “dtu_default” exists.Added function
validate_uncertainty_tableto validate an uncertainty table is formatted correctlyAdded function
total_uncertaintyto calculate the total uncertainty in percentage from an uncertainty table. Following the GUM guideline on adding uncertainties.Added function
uncertainty_summaryto print a formatted summary of the uncertainty tableAdded function
total_uncertainty_factorto calculate the uncertainty factor (the factor that can be directly multiplied to add the uncertainty to an AEP estiamtion)
Bug fixes
clip_with_marginnow returns aValueErrorwhen the bbox crosses the datelineread_raster_mapwas checking for too high roughness twice, one is enoughIf duplicate heights are passed to
create_datasetwithstruct=stacked_pointit will remove the duplicates as required in thestacked_pointstructure.in
gdf_to_dswe must create the target dataset using unique (west_east,south_north) points forstacked_pointand uniquewest_eastandsouth_northfor cuboids to be able to round tripds_to_gdfandgdf_to_ds.get_vector_map(bb, “CORINE”, source=”dtu”) could sometimes fail with “Exception: Missing required column: id”, this has been fixed
read_vector_map also reads .gpkg files where a geometry column is missing on the landcovertable layer
to_stacked_point now retains input order of west_east/south_north coordinates
Nearest_points will now raise an error if there are duplicate points resulting from the nearest neighbour lookup if the data is in stacked_point or cuboid format. This is required because xarray >2024.02 does not allow duplicates in MultiIndexes anymore. A new keyword argument keep_duplicates controls the behaviour, the default being True, i.e. when possible behaviour is the same as before.
In the function
wk.spatial.add_crsassigning a projection with more detailed info given in a proj4 string or custom CRS was overwritten when an EPSG was found for the projection. This is now fixed and the full custom CRS is added.Fixed
wk.spatial.interp_unstructured_liketo broadcast single-point sources correctly to target.Fix bug in
nearest_pointswhenkeep_duplicates=Falseandreturn_distance=True: it threw an error that the arrays were not the same size.
Breaking changes
empty_wasp_site_factorsrenamed toempty_wasp_site_effectsin
empty_z0mesoargumentsite_factorswas renamed renamed tosite_effectsin
empty_pwcargumentsite_factorswas renamed renamed tosite_effects
Argument
nwsbins,nws,n_binshas been renamed ton_wsbinsorwsbins(in case of array-like argument) in the following functions:bwc_from_tswccreate_ws_bin_coordscreate_ws_bin_coords_from_values
Argument
nsec,nsecs,nwd,nbinshas been renamed ton_sectorsin the following functions:create_sector_coordscreate_direction_coordscreate_sector_coords_from_edgeswd_to_sectorbwc_from_tswc
Argument
num_argshas been renamed ton_argsin the following functions:ltc_validate
Argument
ws_bin_widthhas been renamed towsbin_widthin the following functions:create_ws_bin_coordsbwc_from_tswc
Metadata variable name
aep_deficithas been renamed topotential_aep_deficitFunctions
read_raster_mapandraster_map_to_filewere removed in favour of the new functionsread_elevation_raster,write_elevation_raster,read_landcover_raster, andwrite_landcover_raster.Functions
read_vector_mapandvector_map_to_filewere removed in favour of the new functionsread_elevation_vector,write_elevation_vector,read_landcover_vector, andwrite_landcover_vector.Changed most instances where “header” is used to “description”
get_vector_mapreturns polygons instead of lines.Switched configuration file from ini to toml, old file will be automatically migrated
0.8.0 (2024-06-10)
New features
Enhanced wind turbines class
New functions in
windkit.wind_turbinesto create pointxarray.Datasetrepresentation of WTGs frompandas.DataFrame,geopandas.DataFrameand raw point arrays. Additionally, the module adds a functioncheck_wtg_keysto validate wtg keys andwind_turbines_to_geodataframeto convert the dataset back to ageopandas.GeoDataFrame.
New Long Term Correction module
The new module ẁindkit.ltc contains tools to perform long term correction of wind measurements. It is based on the windkit xarray time series wind climate dataset, therefore it
is compatible with all the windkit toolset.
There are two methodologies available:
class
LinRegMCPimplements a linear regression.class
VarRatMCPimplements a variance ratio linear regression.
There is also a
ltc.scoressubmodule to calculate scores such asr2,rmse,biasandwasserstein distance.
Jupyer notebook examples
The windkit package includes a folder with examples of use. currently there is one jupyter notebook example to use the long term correction module.
New functions to handle wind data
New function
windkit.wd_to_sectorcan return sectors of fixed width or sectors of equal probability (quantiles=True)New function
resample_wind_and_directionto resample a time series wind climatexarray.Datasetto a different sampling frequency.New function
windkit.sector.create_sector_coords_from_edgesthat returns a data array with sector coordinates for any array of sector edges, not necessarily equidistant.
New function to implement cross prediction
When implementing a cross prediction methodology, we need to create a combination of pair of spatial points with the different locations to predict.
The new function windkit.get_cross_predictions allows that, from a xarray.Dataset with several points, return two aligned datasets with the points where we want
to predict from and where we want to predict to.
New functions on empty module
New function
windkit.empty.empty_raster_mapgenerates axarray.Datasetraster map instance filled with eitherNaNor meaningful values.New function
windkit.empty.empty_wv_countreturns random meaningful values and it is more suitable for testing
Improvements to get raster and vector source data
get_vector_mapgets data in vector format from DTU servers (currently only supportCORINE)get_raster_map: added new source dtu, with access toViewfinderandESA_CCI, also allows non-geographic bounding boxesAllow user to put
earth_engine.jsonin home directory for authenticating to usage of google earth engine inget_raster_map.
New functionality to handle conversion between geopandas dataframes and xarray datasets
New function
gdf_to_ds, which converts a geopandas dataframe to a xr.Dataset in the best fitting windkit spatial structure.New function
ds_to_gdf, which converts a xr.Dataset in windkit spatial structure to a geopandas dataframe.
Changes
Added
flow_sep_heightargument in the metadata. This variable is used in pywasp to denote the height where flow separation occurs.Added geostrophic wind climate variables
geo_turnandgeo_wv_freqto metadataMoved
gwc_interpolateto pywasp, because it relies on some code from pywasp and is only useful in a pywasp contextget_roughness_mapandget_raster_mapissues a warning if a landcover table is attempted to be read as roughness.Removed constraint on first
gen_heightto be equal to 10. This is not a requirement for pywasp to work.GML files with an empty description (the default) written by windkit can now be opened in the map editor
bwc_to_tabfilenow creates the parent directory if does not exist, and formats the tab filename based on the dataset coordinates.windkit.Workspace.read_wwhallows WAsP workspaces with displacement height maps (i.e. GML files, WAsP >12.7) to be imported.New function
bwc_validate_structurewhich checks only if the structure is OK for abwcdataset, without checking for the actual values.windkit.bwc_to_tabfilewrites a default header “No Header” in the tab file if the dataset does not have the “wasp_header” attribute.Added ‘use_bounds’ argument to
windkit.spatial.BBox.reprojectto allow the reprojection to respect the concave/convex shape of the bounding box due to reprojection.The order of stacked point’s is now preserved when round-trip via
windkit.spatial.spatial_stackandwindkit.spatial.spatial_unstack.Added additional checks for consistency with PyWAsP use when reading in a roughness map with
windkit.read_raster_mapAdded method
windkit.WindTurbines.to_wtg_dict_and_turbines_dsto convert the deprecatedWindTurbinesobject to a dictionary and axarray.Datasetof turbines.
Bug fixes
Fixed a bug in
windkit.read_bwc, where it did not check correctly whether the requested crs matches the dataset crs.get_raster_mapno longer gives -9999 for areas where no data is available.Fixed a bug in
windkit.bwc_to_tabfile, where it allowed to write datasets with projected coordinates to a tab file, which is not allowed.Fixed a bug in
windkit.bwc_from_timeserieswhere it returned a point structure when the input was a stacked_point.Fixed a bug in
LandCoverTablethat did not allow to instantiate an object when colors or labels are notNone
Deprecations
count_to_ws_freq_by_sectoris deprecated in favor ofbwc_from_counts.binned_wind_climate.bwc_from_weibullis removed in favor ofweibull_wind_climate.wwc_to_bwcwith simpler API passing in axr.Datasetinstead of weibull parameters one by one.WindTurbinesclass is deprecated in favor ofwind_turbines.create_wind_turbines_from_*functions to createxr.Datasetrepresentation of WTGs.get_mapandget_ee_mapare deprecated in favour ofget_raster_map
0.7.0 (2023-11-13)
New Features
Additional interpolation functionality
The interpolation functionality of windkit was expanded with the release, several low-level interpolation routines were added, allowing interpolation to and from all of windkit’s spatial data structures.
Added
windkit.spatial.interp_structured_likefor interpolation from a “cuboid” to any spatial structure, using any of the interpolation methods available inxarray.Dataset.interp.Added
windkit.spatial.interp_unstructured_likeandwindkit.spatial.interp_unstructuredand for interpolation between any spatial structures, usingnearest,linear, orcubicmethods. Additionally, thenaturalmethod can be used peform natural neighbor interpolation for 2Dpointstructured target structures, usingmetpy's implementation <https://unidata.github.io/MetPy/latest/examples/gridding/Natural_Neighbor_Verification.html>.
Additionally a few high level routines were added for interpolation specific fields.
Added
windkit.interpolate_gwcto interpolate a generalized wind climate dataset.Added
windkit.vinterp_wind_speedfor vertical interpolation of wind speedsAdded
windkit.vinterp_wind_directionfor vertical interpolation of wind directions
Improvements to the map_conversion routines
Added
windkit.map_conversion.find_duplicate_linesto identify duplicated lines in a GeoDataFrame, even if the line is reversed.windkit.poly_to_linesnow correctly sets the CRS to match the input data. Before it wasNone.windkit.poly_to_linesandwindkit.lines2polynow have an absolute tolerance argument,atol, which can be used to identify nearby points, which should be joined.
Access to data from Microsoft’s Planetary Computer platform
Elevation and landcover data obtained using
windkit.get_mapcan now use either Microsoft’s Planetary Computer platform or Google’s Earth Engine.Added
windkit.get_era5to download ERA5 data from Microsoft’s Planetary Computer platform.
Calculate additional derived quantities from Weibull and Binned Wind climates
Added new functions
windkit.fit_weibull_wasp_m1_m3_fgtm,windkit.fit_weibull_wasp_m1_m3, andwindkit.fit_weibull_k_sumlogmfor fitting weibull distributions to wind speed moments.Added
windkit.weibull_cdfandwindkit.weibull_pdfcalculate the cdf and pdf of a weibull distribution.Added
windkit.weibull_freq_gt_meanto calculate the fraction of probability mass above the mean of a weibull distribution.Added
windkit.bwc_ws_cdfandwindkit.bwc_freq_gt_meanare similar functions for binned wind climates.
Convenience functions to access standard land cover tables for common datasets
Added
windkit.LandCoverTable.get_tableand it’s top-level aliaswindkit.get_land_cover_tableto get a land cover table for a given land cover dataset. Landcover tables are currently provided for CGLS-LC100, CORINE, GlobCover, MODIS, WorldCover, and ESA_CCI.
Even more spatial functionality
Added
windkit.spatial.clip_with_marginto clip a raster-like dataset to the bounds of another dataset plus a margin. This is useful for clipping a dataset before doing other operations with it (e.g. interpolation) to reduce computation time.Added
windkit.spatial.equal_spatial_shape, to check if two xarray objects have the same struct and spatial shape. This differs fromwindkit.spatial.are_spatially_equal, which requires the values to also be the same.Added
windkit.spatial.coversto check if a cuboid dataset covers another spatial dataset (point, stacked_point, or cuboid, or polygon).
Further improvements to wrg and rsf file handling
windkit.read_wrgfile,windkit.read_rsffilehave a new boolean argumentuse_production, where if it is True, the power colum in the file is interpreted as gross AEP, and when False, the power column in the file is interpreted as power density.windkit.read_wrgfile,windkit.read_rsffilehave a new boolean argumentuse_productionwhere if it is True, thegross_aepdata variable is written to the file, and if False, thepower_densitycolumn is written to the file.
Bug fixes
windkit.LandCoverTable.from_dict_ora: Sets the correct values ofz0fracanddfracin the LandCoverTable description.windkit.BBox.buffernow works withshapely 2.0.Changed the default
nodatavalue forwindkit.spatial.warpfromnp.nantoNone, which results in a value of-9999for integer fields, andnp.nanfor float fields. This fixes an issue with integer data, for whichnp.nanis undefined.windkit.read_rsffileno longer returns a unneededpointcoordinate, whento_cuboid=False.empty.empty_gwcuses the same random number generator for all data variables, ensuring the same seed gives the same numbers.
Changes
windkit.generalized_wind_climate.read_gwcperforms validations checks for all formats, not onlynetCDFwindkit.generalized_wind_climate.to_libfiledetects if path is a file or a directory and creates subdirectories if they do not exist.windkit.generalized_wind_climate.to_libfileformats.libfilename using the coordinates if no name is given, similar to what is done with multiple files.function
gwc_validateand decoratorgwc_validate_wrapperperform extra validations on generalized wind climate datasets. The first generalized height must be 10.0, the first generalized roughness must be 0.0, and both must have at least 2 entries.windkit.read_cfdres, now always returns a dataset with the coordinatessouth_northandwest_eastsorted from low to high.windkit.read_vector_mapwill raiseRuntimeErrorwhen trying to read a.mapfile with displacement height, which is not supported.wk.read_rsffilenow allows .rsf files with a single-point to be converted to cuboid.Added
windkit.rotor_equivalent_wind_speedfunction for calculating REWSAdded
windkit.read_wwcthat creates and validates a weibull wind climatexarray.Datasetfrom a file.Added
datum_nameargument towindkit.spatial.BBox.utm_bbox_from_geographic_coordinateto allow the user to specify the datum name for the UTM projection.empty.empty_wasp_site_factorsandempty.empty_met_fieldsare filled with random numbers.empty.empty_pwccan include any desired combination of met field and site factors. Defaults toA_combined,k_combined,power_densityfor met fields andsite_elevfor site factors.empty.empty_gwchas a new boolean argumentwdfreq_constant, which allows you to create a generalized wind climate object wherewdfreqis constant along thegen_height. This is used to create datasets that can be written to the.libfile format.empty.empty_gwcretains the shape of scalar structured datasets, i.e. a single point with no point dimension, only coordinate values. This structure is common when selecting a single location using.selor.isel.Added
windkit.empty.empty_tswcthat generates a time series wind climatexarray.Datasetwith random but meaningful values.Added
split_combomapCLI utility, which reads a combo.mapfile and returns two.gpkgfiles, one for elevation and one for landcover.
Deprecations
windkit.spatial.interpolate_to_griddeprecated in favor ofwindkit.spatial.interp_structured_likeandwindkit.spatial.interp_unstructured_like
Breaking changes
windkit.poly_to_linesno longer has aclosed_mapargument. Instead, whenbackground_lc_idis set, all empty space is filled with the provided id. This allows for maps that are no longer rectangular, e.g. due to reprojection, to be properly converted to line maps.Removed accessors, which were previously registered for several wind climate data structures. You will need to use the functions instead.
0.6.3 (2023-07-18)
New Features
Enhanced bounding box object
Several new methods were added to the BBox object to make it easier to work with.
Create BBox objects in more ways:
BBox.from_boundsas alias toBBox.from_cornerptsand set default crs toEPSG:4326BBox.from_point_and_bufferto create a bbox from a x,y-point, a buffer size, and a crsBBox.utm_bbox_from_geographic_coordinateto create a bbox from a geographic coordinate (point) and a buffer in meters, projecting to the appropriate UTM coordinates.
Simplified reproject to geographic and UTM coordinates
Added method
BBox.reproject_to_geographic()to reproject a bbox to geographic coordinatesAdded method
BBox.reproject_to_utm()to reproject a bbox to UTM coordinates
Return data in common GIS formats using:
Added method
BBox.polygonproperty to return a shapely polygonAdded method
BBox.envelope()to return an enveloped bbox in the current crs
Create a simple plot of your BBox using
BBox.plot()
Formatting improvements when writing .wrg/.rsf files
windkit.to_rsffileandwindkit.to_wrgfilenow attempts to match the WAsP formatting more closely and a newformattersargument allows the user to specify the formatting for each column. This allows for more control over the formatting of the output file. Additional formatting checks have also been added to ensure that the formatting is correct.
Require regulation_type for wtg data structures
The WindTurbineGenerator now requires a regulation_type variable. When reading in a WTG using
windkit.read_wtg, the default mode is pitch. You can set it to stall or have it autodetected using the newwindkit.wind_turbine.estimate_regulation_typefunction.Validation functions have been added to the WTG object type, so you can now ensure that your Dataset has the correct format before using the WTG.
Allow use of Polygons for defining landcover data
windkit.read_vector_mapNow can read polygon based landcover vector map files ingpkgformat, which is commonly used in GIS tools. The function has a new parameterbackground_lc_idthat is needed to setup the background for polygon based vector maps.
Changes
windkit.read_vector_map: For landcover data ingpkgformat,idis now the default name used to identify landcover ID’s in the landcover table. For oldgpkgfiles where the nameindexis used,windkit.read_vector_mapwill print aFutureWarning.Remove dependency on
cf-xarray, as we have our own metadata vocabulary. This fixes an issue where Pooch was an optional dependency ofcf-xarray, but required for the functionality used by WindKit.
BugFixes
Prevent exception when running in the python interpreter and calling
windkit.metadata.update_history. Now a the generic message “Unknown python interpreter command.” is added to the object history in this scenario. To get a correct history, it is recommended to use iPython for interactive sessions.Fixed a bug in
BBox.buffer, which would cause negative buffering to not preserve bbox shape
0.6.2 (2023-06-20)
New Features
New file reading functions
windkit.read_timeseries_from_pandasandwindkit.read_timeseries_from_csvbuild a time-series wind climatexarray.Datasetfrom time-series data in tabular form, either apandasDataframe or acsvfile. The functions attempt to auto-detect the wind speed and wind direction columns based on a standard list of names if they are not provided.windkit.read_cfdresreads a WAsP CFD.cfdresfile into anxarray.Datasetstructure.
Detection of CRS from WAsP .map files
windkit.read_vector_mapand by extensionwindkit.read_elevation_mapandwindkit.read_roughness_mapnow try to detect CRS information from the header of WAsP.mapfiles, which can be added using recent versions of the WAsP MapEditor. In case there is a problem (e.g. wrong format) it will raise an error.
Updates to vertical profile plotting
windkit.plot.vertical_profileFunction now works for data arrays without their attributes set. If the height coordinate does not have attributes,Height [m]will be used for the y-axis. If the data variable to plot does not have attributes,DataArray.namewill be used for the x-axis.windkit.plot.vertical_profileno longer allows plotting of objects with atimecoordinate. This is due to performance limitations when plotting potentially thousands of points when a time-series object is passed.
Breaking changes
When creating a file using
windkit.to_rsffileandwindkit.to_wrgfileor reading a file usingwk.read_rsffileandwk.read_wrgfile, the elevation variable has been renamed fromelevationtosite_elev. This now matches the variable name used in PyWAsP.class
windkit.WindTurbinesdoes not allow wind turbinexarray.Datasetwith more than one mode.
Changes
windkit.spatial.nearest_pointswill issue a warning instead of aValueErrorwhen it is used on datasets with geographical coordinates.windkit.to_rsffileandwindkit.to_wrgfilecalculate necessary parameters met_fields, “power_density”, “combined_A”, “combined_k”, and “wspd”, from a wwc if they aren’t included.
Bug Fixes
Fixed a formatting bug in
wk.to_rsffileandwk.to_wrgfilethat resulted in incorrect column widths.
0.6.1 (2023-03-16)
New Features
windkit.wtg_cpfunction returns the power_coefficient for given wind speeds from an wind turbine generator.Added lookup table to convert WAsP Map Editor named projections to EPSG codes. This allows for projection to be autodetected from some GWC files.
Breaking changes
Removed
coordsfromwindkit.read_gwc. Instead you should use the separatewest_east,south_north, andheightarguments. Also removed**kwargs, as there was only a single optionheader, which is now its own argument.
Changes
Updated pyproj dependency to minimum 3.0
Added
gen_heightsandgen_roughnessesarguments towindkit.empty.empty_gwcto allow users to specify these coordinate values.Removed the
modeargument fromwindkit.wtg_power,windkit.wtg_ct, andwindkit.wtg_cp, as they now work with any number of modes in the WTG. If you wish to use a single mode from a wind turbine object, you should select using theiselorselmethod.
Bug Fixes
Allow projections that don’t have an EPSG code to be added using
windkit.spatial.add_crs.Scalar spatial datasets would fail in
windkit.spatial.count_spatial_points.Ensured that
wk.Workspace.get_gwccould parse GWC objects from WAsP 12.7 and 12.8 workspaces.Fixed bug in
windkit.spatial.to_stacked_point, where the order of thewest_eastandsouth_northcoordinates would be flipped from expected. This caused an issue when converting topointand then back tostacked_point.Prevent creation of NaN values for some curves when using
windkit.read_wtgto read.wtgfiles with different modes and different wind speed tables.Bug fix in
wind_climate._is_bwcwhere an exception was not properly caught.
0.6.0 (2023-01-29)
Several new features in this release including support for Wind Turbines, the ability to convert roughness lines to roughness polygons, and the ability to read PWC files. Several important bug fixes also added.
New Features
Support for wind turbines and AEP data
New metadata attributes for annual energy production and wind farm flow map
New class
windkit.WindTurbinesto hold collections of turbine locations and WTGs (power/ct curves and other details).Added metadata for wind turbine generator
xarray.Dataset.New plotting function
windkit.plot.plot_wind_turbine_locations.
Ability to convert roughness lines to polygons and back
New module
windkit.map_conversionThat allows the user to both create polygons from lines and convert polygons to lines, based ongeopandas.GeoDataFrame. It contains the following:LineMapandPolyMapclasses: These classes enable conversion and nice plotting of their types.lines2polyandpoly_to_lineshelper functions that perform the conversion from lines to polygons and from polygons to line respectively, using the librarygeopandas.GeoDataFrame.
New module
windkit.plot.landcover_mapto plot thegeopandas.GeoDataFramepolygons or lines as a map.New module
windkit.plot.colorto provide color functions for maps with a focus on roughness coloring.Class
windkit.LandCoverTablehas a new methodadd_colors_to_tableto store colors to be used in map plots.
New spatial functionality
New function
windkit.spatial.interpolate_to_gridto resample data to a target grid.New function
windkit.spatial._get_latitudethat returns data-array of latitude values in wgs84.New function
windkit.spatial.count_spatial_pointscounts how many points are in a windkit dataset or dataarray.
Enhancements to windkit.get_map.get_ee_map
Added NASADEM as elevation dataset
Added worldcover as landcover dataset
Added option to convert to vector in the cloud.
Ability to read PWC files
windkit.read_pwcfilereads WAsP.pwcpredicted wind climate file in XML format and returns a weibull wind climatexarray.Dataset
Breaking changes
Requires
geopandas>=0.11.Requires
rioxarrayfor reading raster GIS files.
Deprecations
Changes
To support
pyproj3.4.0, changed frompyproj.crs.CRS.is_exact_sametopyproj.crs.CRS.equals, and dropped deprecatedskip_equivalentkwargs.Drop
south_northandwest_eastcoords before reassigning them as required in futurexarrayversion.Added height dependent wind direction frequencies to GWC I/O routines
For the .lib-file reader frequencies are duplicated across all gen_heights
For the .lib-file writer a check is made to ensure all frequencies are these same across heights. If they are not, a gen_height is required to be set by the user.
Improvements
Sped up creation of .lib strings for GWC objects. In testing 15 sites, went from 11s to <1.
Retain meta data of
wsbincoordinates now also present after combiningbwc’s
Bug Fixes
Windkit.wwc_mean_windspeedandwindkit.wwc_power_densitypreviously calculated emergent wind case using all-sector A&k values. Now it is correctly calculated using sectorwise, and an error is thrown if bothemergentandbysectorkwargs areTrue.Fixed reading
tifandgrdfiles with negativedx.Catch exception in
wind_climate._is_bwc.Prevent modification of input dataset when calling
weibull_wind_climate.weibull_combined.Return point or stacked-point dataset for when calling
windkit.spatial.create_datasetwith duplicatedwest_eastandsouth_northvalues. Previously a cuboid was returned with duplicated points collapsed.Use fixed column parsing in
read_rsf/read_wrgrather than space splitting, when reading the number of sectors.Ensure temporary file created when using
windkit/get_map.pyis always removed.Create correct BWC when reading data with with irregular bins (i.e. as exported from windpro).
0.5.1
Changed name of author’s attributes from name/email to author/author_email
Fixed bug for 1d nearest point estimation. The KDtree throws an error if we do not expand the 2d point [x,y] to [[x],[y]]
Removed unneeded dependencies
0.5.0
New Features
Added functions
read_wrgfileandto_wrgfileto read and write .wrf resource grid filesAdded functions for simple wind-related calculations:
windkit.wind_speed_and_directioncalculates wind speed and direction from horizontal wind vectors U and Vwindkit.wind_vectorscalculates horizontal wind vectors U and V from wind speed and directionwindkit.wind_direction_differencecalculates the smallest (signed) circular difference between wind directions in degrees.windkit.wind_speedcalculates horizontal wind speed from vectors U and Vwindkit.wind_directioncalculates horizontal wind direction from vectors U and Vwindkit.wd_to_sectorto calculate the bin-index for wind directions for a given number of bins/sectors
Support for new Xarray-based Wind Turbine Generator (WTG) object added
New wind climate dataset validator function and decorator.
The function receives an
xarray.Datasetand returnsTrueorFalse.The decorator wraps a function that receives a wind climate dataset and raises a
WindClimateValidationErrorif the dataset is not valid.It checks dimensions, attributes and data variables.
The functions available are:
bwc_validate,bwc_validate_wrapperfor binned wind climate dataset, imported fromwindkit.binned_wind_climatewwc_validate,wwc_validate_wrapperfor weibull wind climate dataset, imported fromwindkit.weibull_wind_climategwc_validate,gwc_validate_wrapperfor generalized wind climate dataset, imported fromwindkit.generalized_wind_climatets_validate,ts_validate_wrapperfor time series wind climate dataset, imported fromwindkit.time_series_wind_climate
New
WindClimateValidationError, raised by the newly introduced wind climate dataset validators.New method
BBox.to_geoseries()that converts Bounding box togeopandas.GeoseriesNew
emptymodule that generatesxarray.Datasetinstances filled with eitherNaNor meaningful values.Suitable for testing.
Current available functions are:
empty.empty_wasp_site_factors(): Create empty site-factors datasetempty.empty_bwc(): Create empty binned wind climate dataset filled with meaningful random numbers, i.e. they are generated with a weibull distribution, the sum ofwdfreqis 1, etc.empty.empty_wwc(): Create empty weibull wind climate dataset filled with meaningful random numbers, e.g.the values fromAare generated from a uniform function between5and10and the values forkfrom a uniform function between1.5and2.5.empty.empty_gwc(): Create empty generalized wind climate dataset with the data variables are filled with meaningful random numbers, e.g. the values fromAare generated from a uniform function between5and10and the values forkfrom a uniform function between1.5and2.5.empty.empty_met_fields(): Create empty dataset filed withmet_fieldsempty.empty_z0meso(): Create empty site_factors with onlyz0mesoandslfmesoempty.empty_pwc(): Create empty predicted wind climate with optional variables
New plotting functions in module
windkit.plotwindkit.plot.vertical_profile()plots the vertical profile of the dataArray or dataArrays introduced.windkit.plot.time_series()creates a time series plot.windkit.plot.single_curve()andwindkit.plot.power_ct_curves()add plots for electrical power output curve, thrust curve, RPM, Ct, Cp or any other curve the user wants to pass through.
New function
windkit.time_series.read_ts_windpro_txtReads windpro format txt file into a
xarray.Dataset
Removed
Removed
windkit.binned_wind_climate.dir_to_secin favor ofwindkit.wd_to_sectorModules
WaspVectorMapandWaspRasterMapwere moved topywaspand are no longer available.
Removed legacy WTG objet
WindTurbine
Changes
windkit/windturbine.pyAdded function
read_wtgto create anxarray.Datasetrepresentation of a turbineAdded
wtg_powerandwtg_ctto return power and ct for given wind speedAdded
wtg_to_pywake, which makes a PyWake wind turbine class from the dataset
renamed
vectormaptovector_maprenamed
rastermaptoraster_maprenamed
elevationmaptoelevation_maprenamed
roughnessmaptoroughness_mapwindkit.read_elevation_mapandwindkit.read_roughness_mapnow reads both raster and vector maps.Changed the default behavior of
windkit.spatial.clipfor rasters/cuboids so small padding is added to the mask, ensuring that raster/cuboid pixels/cells on the edge of the mask are included in the clipping. The previous behavior can be achieved by settingpad=FalseUpdated
windkit.spatial.clipforpointxr.datasetto always include points that are on the edges of the mask (previously only points inside were included)Updated BWC “header” and GWC “desc” to both be named “wasp_header” (only included for objects originating from WAsP files or methods).
Updated to always use “crs” as spatial reference argument name
Mirrored
spatial.to_rasterasspatial.to_cuboid
Improvements
Updated
read_rsffileandread_wrgfileto automatically infer the number of sectors in the data.Updated
windkit.spatial.clipso it uses a faster clipping method (_clip_to_bbox_raster) when the masking is provided as aBBoxobject. This speeds up clipping speed significantly.Allowed
ws_binsto be pythonrangeinwindkit.binned_wind_climate._freqs_to_dataset()Functions
windkit.spatial.to_pointandwindkit.spatial.to_raster_pointnow also work on scalar datasets.Fix bug in
metadata.update_var_attrsto store “Object type” as the string “None” to properly write to netCDFLandcover GMLs use custom reader/write to ensure compatibility with WAsP & Map Editor
Plotting documentation improved by rendering jupyter notebooks on it using
nbsphinxextension forsphinxPlotting testing with jupyter notebooks