-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for time-series data #241
Conversation
Pull Request Test Coverage Report for Build 1180799700
💛 - Coveralls |
raise ValueError( | ||
f'{v} is not a valid value for the "type" field. ' | ||
'Only the default value is accepted.' | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mostaphaRoudsari,
I am sure, you'll ask me to use Enum here. But I have deliberately not done that.
animation = Animation( | ||
timeSteps=[AnimationTimeStep(time=time_step, Grid=grid_obj) | ||
for time_step in time_steps]) | ||
data['animation'] = animation.dict() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mostaphaRoudsari,
I am creating a dictionary here and that's the reason I am not using Enum in schema. I get json serialization error if I use Enum here.
data['animation'] = animation.dict() | ||
|
||
with open(index_json, 'w') as file: | ||
json.dump(data, file) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am aware that I can bypass the error by using json.dumps here dut I want to avoid doing that. Since incase of thousands of time steps this data here will be huge.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good! I didn't really leave a comment on this module. I think once we do a refactor of honeybee-radiance output files most of these functionalities will change anyways.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @devngc! Thank you for the PR and sorry for the late review.
My only strong comment is about changing to_vtkjs
to a staticmethod
. I think we should keep to_vtkjs
as the main method for exporting the model to vtkjs. Other than that it looks good to me.
@@ -60,20 +60,29 @@ def translate(): | |||
show_default=True | |||
) | |||
@click.option( | |||
'--validate-data', '-vd', is_flag=True, default=False, | |||
'--validation', '-vd', is_flag=True, default=False, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is a flag I think --validate
is a better option that --validation
help='Validate simulation data before loading on the model. This is recommended' | ||
' when using this command locally.', show_default=True | ||
) | ||
@click.option( | ||
'--time-series', '-ts', is_flag=True, default=False, | ||
help='Load time series data on a honeybee-vtk moodel.', show_default=True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
help='Load time series data on a honeybee-vtk moodel.', show_default=True | |
help='Indicate data input is time series data.', show_default=True |
if time_series and file_type != 'vtkjs': | ||
raise ClickException( | ||
'Time series data can only be exported to vtkjs. Use the file-type options' | ||
' to set "vtkjs" as the output file type.') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
' to set "vtkjs" as the output file type.') | |
' to set the output file type to "vtkjs".') |
grid_type: A string indicating whether the model has points and meshes. | ||
""" | ||
# file path to the json file | ||
grids_info_json = pathlib.Path(data.path).joinpath('grids_info.json') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What you have done is totally fine but I think this is prettier!
grids_info_json = pathlib.Path(data.path).joinpath('grids_info.json') | |
grids_info_json = pathlib.Path(data.path, 'grids_info.json') |
f'In data {data.identifier.capitalize()}, since min and max' | ||
' values are not provided, those values will be auto calculated based' | ||
' on data. \n' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels a bit wordy what about this:
f'In data {data.identifier.capitalize()}, since min and max' | |
' values are not provided, those values will be auto calculated based' | |
' on data. \n' | |
f'Legend min and max values are autocalculated for {data.identifier.capitalize()}.\n' |
Also I don't know if we want to give this warning at all. It might confuse our users more than being helpful.
raise TypeError( | ||
'Not a valid json file.' | ||
) | ||
else: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is mostly for making the code pretty.
I would not use else
here since there is no follow-up section in the code. if it doesn't create an exception then the rest of the code should be executed anyways.
if not data.hide: | ||
if not time_series: | ||
result = _get_model_with_point_in_time_data( | ||
validation, data, model, grid_type, scene, legend) | ||
else: | ||
result = to_time_series_folder(data, model, grid_type, hbjson) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit of a code smell. The fact that we need both the Model and the Scene to load the data and config doesn't feel right.
Maybe this method should be called from inside the Scene or Model object? Let's see how it works.
@@ -260,37 +261,29 @@ def _add_objects(self, data: Dict) -> None: | |||
except AttributeError: | |||
raise AttributeError(f'Invalid attribute: {attr}') | |||
|
|||
def to_vtkjs(self, folder: str = '.', name: str = None) -> str: | |||
"""Write a vtkjs file. | |||
def to_point_in_time_folder(self, target: pathlib.Path = None) -> pathlib.Path: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be an internal method?
return point_in_time_folder | ||
|
||
@staticmethod | ||
def to_vtkjs(temp_folder: pathlib.Path, folder: str = '.', name: str = None) -> str: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not a good move in my opinion from the API point of view. to_vtkjs
is what we have used as the standard method to write the model to a vtkjs file. Making it a static second-level method is not what I would do.
In any case, it is strange to have temp_folder as a required input. Moreover we should either use strings or pathlib.Path for folder inputs. It looks so random that the first one is expecting a Path and the second folder is a string.
data['animation'] = animation.dict() | ||
|
||
with open(index_json, 'w') as file: | ||
json.dump(data, file) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good! I didn't really leave a comment on this module. I think once we do a refactor of honeybee-radiance output files most of these functionalities will change anyways.
Hi @mostaphaRoudsari,
resolves #223