Meteo Object Service

The ObjMeteoService gives access to some functionality from the meteo object. It includes meta data about the meteo objects and offers export and import functionality. Data can be loaded from csv file (in specific windPRO format), windPRO objects, or mesores.

The meteo object is the only object that does not have a dedicated Set method. The reason for this is, that the Meteo Object is very complex. There are dedicated enpoints to manipulate the Meteo Object to ensure that the behaviour stays clearly defined.

There are three function that are used to generate a meteo object from file: AddImportSetup, AutoCreateFromImportSetup, and LoadAllData. They correspond to the work flow in windPRO when importing data files. .. warning:: Do not use AutoCreateFromImportSetup and LoadAllData``on meteo objects that have e.g. been generated from a windPRO export with ``ImportFromWpExportFile. It will create undefined behaviour in the meteo object.

Properties of the object can be found here TApiObjMeteo.

import time
"""
Copyright 2023 EMD International
License for this script: MIT https://opensource.org/license/mit/
License for windPRO commercial software: https://www.emd-international.com/contact-us/general-terms-conditions-sale/
"""

import os
from windproapi.utils import get_windpro_sample_path
from windproapi import WindProApi
from windproapi import nan_to_skipvalue

# Opening windPRO
_windproapi = WindProApi()
working_dir = os.path.join(get_windpro_sample_path('4.0'), 'ObjMeteoService')
os.makedirs(working_dir, exist_ok=True)
testdata_path = os.path.join(os.path.dirname(__file__), '../data')
_windproapi.start_windpro_random_port()

# Services
project_service = _windproapi.get_service('ProjectService')
objects_service = _windproapi.get_service('ObjectsService')
obj_meteo_service = _windproapi.get_service('ObjMeteoService')
factory = _windproapi.get_factory('WindproService')

# Making a new projects and adding meteo objects
project_path = os.path.join(working_dir, 'ObjMeteoService.w36p')
lng = -101.402205
lat = 46.732303

project_service.NewProject(lng=lng, lat=lat, filename=project_path)
time.sleep(1)

# Creating a new meteo object and importing a previous export file
new_obj = objects_service.AddObject(apiObjType='MeteoObjectData',
                                    lat=lat,
                                    lng=lng,
                                    userDesc='New Meteo obj')
exp_file = os.path.join(testdata_path, 'meteo_export', 'newsalem_export_single_height.csv')

# Import returns True if it completed correctly
res = obj_meteo_service.ImportFromWpExportFile(handle=new_obj.Handle, importFilename=exp_file)
# Getting the meteo object from the generic object.
meteo_obj = obj_meteo_service.GetMeteoObject(handle=new_obj.Handle)
print(meteo_obj)

# Creating a new meteoobject from a mesores file
# No information on the location is necessary
mesoFn = os.path.join(testdata_path, 'mesores', 'new_salem_01-01-2020;01-02-2020.mesores')
# Mesores files can contain multiple poitns thereore a list of handles is returned
mesoHandles = obj_meteo_service.CreateFromMesores(mesoResFilename=mesoFn)
meteo_obj = obj_meteo_service.GetMeteoObject(handle=mesoHandles[0])
print(meteo_obj)

# Exporting data to windPRO format
# Heights need to be identified by their index
int_array = factory.TROArray_System_Integer_([1, 2])
meto_export_path = os.path.join(working_dir, 'meto_exp_test.txt')
obj_meteo_service.ExportMeteoObjectToFile(handle=mesoHandles[0],
                                          heightUids=int_array,
                                          exportFilename=meto_export_path)

# Deleting and reimporting object
objects_service.DeleteObject(mesoHandles[0])

new_obj = objects_service.AddObject(apiObjType='MeteoObjectData',
                                    lat=lat,
                                    lng=lng,
                                    userDesc='Reimported mesodata obj')
obj_meteo_service.ImportFromWpExportFile(handle=new_obj.Handle, importFilename=meto_export_path)

meteo_obj = obj_meteo_service.GetMeteoObject(handle=new_obj.Handle)
print(meteo_obj)

# Getting Weibull statistics
exp_file = os.path.join(working_dir, 'newsalem_statistics.tab')
obj_meteo_service.SaveFreqTableToTab(meteo_obj.Handle, 1, exp_file)

# Importing data from csv with an import filter
# make a new object
new_obj = objects_service.AddObject(apiObjType='MeteoObjectData',
                                    lat=lat + 0.05,
                                    lng=lng,
                                    userDesc='Mast from New Salem')
exp_file = os.path.join(testdata_path, 'meteo_export', 'newsalem_export_single_height.csv')

# Getting meteo object
meteo_mast = obj_meteo_service.GetMeteoObject(handle=new_obj.Handle)

# Meteo Import file needs to be set up
meteo_import = factory.TApiMeteoImportSetup()
import_file = os.path.join(testdata_path, 'meteo', 'import_filter.wls')
meteo_import.LoggerSetupFile = import_file
meteo_import.DontUseInSetup = False
meteo_import.IsOnlineData = False

# For the import setup we need infomration on the folder structure and where the data is located.
# Multiple folders could be included, in this case it is only one
folder_items = factory.TApiFileFolderItems()
folder_item = factory.TApiFileFolderItem()
folder_item.FFType = factory.TFileFolderListType('fftFile')
folder_item.FFName = os.path.join(testdata_path, 'meteo', 'New_Salem_2_South_60m_FINAL.csv')
folder_item.FFMask = None
folder_item.FFInclSubFolder = False
folder_item.FFTreatFolderAsZip = False
nan_to_skipvalue(folder_item)
folder_items.TApiFileFolderItem.append(folder_item)

# Add Folder structure to serach paths
meteo_import.SearchPathes = folder_items

# Add import setup to meteo object
nan_to_skipvalue(meteo_import)
obj_meteo_service.AddImportSetup(handle=new_obj.Handle, importSetup=meteo_import, loggerSetupFn=import_file)

# Automatically create heights. Needs to be done before loading data to determine what data should be loaded in.
obj_meteo_service.AutoCreateFromImportSetup(handle=meteo_mast.Handle)

# Load the actual data
obj_meteo_service.LoadAllData(handle=meteo_mast.Handle)