OpenStudio 2.0 added runner
which has a lot of powerful methods to get data from the workflow, including information about files. It's also used to write log messages out to the resulting overleaded osw
file.Specific to your question, the osw
file typically has one or more measure and file paths. If none are listed there are still a few default locations even if not included in the OSW. Below is an example
"measure_paths": [
"../../../measures"
],
"file_paths": [
"../../weather",
"../../seeds",
"../../seed"
],
If you type runner.workflow.absoluteMeasurePaths
you get the absolute paths. You can leave of absolute to get relative paths, and this work for file paths as well.
In this boring example it looks like what is below. While may uses have measures adjacent to the osw
the OpenStudio workflow supports measures being anywhere.
/Users/user_name/Documents/project_dir/measures
/Users/user_name/Documents/any_directory_I_want_to_use
/Users/user_name/Documents/github/my-measures-gem/lib/measures
If your goal in the end is to find a file, there is a method for that called findFile
. Here is an example of this where I take a weather file name as a measure argument, and I find it to load in the run method. I key point here is it stops as soon as it fines a file by that name, so as best practice you should not have any files of the same name in different directories listed in file_paths
. This is also true fro measure_paths
. If you have measures named my_measure
in different directories, it won't be clear which one is being run.
osw_weather_file = runner.workflow.findFile(weather_file_name).get.to_s
This last part is a bit off topic but good to show while I'm talking about runner
. This method takes an argument name from the current measure, and then looks for upstream measures with that same argument name. The intent is to support using the upstream value to set a downstream value so they are in sync. This is useful if doing an algorithmic parametric analysis. In that case the first instance of the argument would be set to a variable, and the other instance would just be an argument. A variation on this can cake a runner.registerValue
written by an upstream measure` instead of just input arguments. For example maybe you take one path if the upstream argument added more than 10 of some object but a different path if it has less, or maybe you want the name of a model object made or altered earlier without having to search for it. You can think of it a bit like variables that can be passed between measures.