add function to read from a csv to test helper#14486
Conversation
…pplication-function-to-read-from-a-csv
…ll stresses or strains or displacements
…pplication-function-to-read-from-a-csv
WPK4FEM
left a comment
There was a problem hiding this comment.
Hi Sabine,
Thank you for the correction of the order of the labels. For me this is good to go, but I'm by no means a python expert. Please await also Anne's approval.
Regards, Wijtze Pieter
avdg81
left a comment
There was a problem hiding this comment.
Hi Sabine,
Thanks for generalizing the functionality to read expected results from CSV files. As I said before, this is even nicer than the code that you started from. 👍
I have a few minor suggestions, but overall, this PR is (almost) ready to go.
| def get_values_from_csv(csv_filepath, keys, values): | ||
| result = {} | ||
| with open(csv_filepath, newline = "") as csv_file: | ||
| reader = csv.DictReader(csv_file) | ||
| for row in reader: | ||
| if len(keys) == 1: | ||
| key = int(row[keys[0]]) | ||
| else: | ||
| key = tuple(int(row[key]) for key in keys) | ||
| expected_values = {value: float(row[value]) for value in values} | ||
| result[key] = expected_values | ||
| return result |
There was a problem hiding this comment.
I like the generality of this function. Perhaps with a little bit of renaming and extracting one helper function, it becomes even easier for me to read. My suggestion makes the code a little longer, but hopefully that is worth it. What do you think?
| def get_values_from_csv(csv_filepath, keys, values): | |
| result = {} | |
| with open(csv_filepath, newline = "") as csv_file: | |
| reader = csv.DictReader(csv_file) | |
| for row in reader: | |
| if len(keys) == 1: | |
| key = int(row[keys[0]]) | |
| else: | |
| key = tuple(int(row[key]) for key in keys) | |
| expected_values = {value: float(row[value]) for value in values} | |
| result[key] = expected_values | |
| return result | |
| def _make_key(key_field_names, row): | |
| if len(key_field_names) == 1: | |
| return int(row[key_field_names[0]]) | |
| return tuple(int(row[field_name]) for field_name in key_field_names) | |
| def get_values_from_csv(csv_filepath, key_field_names, value_field_names): | |
| with open(csv_filepath, newline = "") as csv_file: | |
| reader = csv.DictReader(csv_file) | |
| return { | |
| _make_key(key_field_names, row): { | |
| field_name: float(row[field_name]) for field_name in value_field_names | |
| } | |
| for row in reader | |
| } |
FYI, I wrote this from the top of my head, and I didn't test it. Please, have a close look and check for any mistakes from my side. Thank you.
There was a problem hiding this comment.
It works and I think it is nice. Thank you for the suggestion :)
| result[key] = expected_values | ||
| return result | ||
|
|
||
| def get_values_from_csv_as_vectors(csv_filepath, keys, values): |
There was a problem hiding this comment.
Nice function to easily construct a vector. I like it. 👍
Perhaps also here, we can rename the arguments to key_field_names and value_field_names. What do you think?
| self.assert_integration_point_tensors(result, "ENGINEERING_STRAIN_TENSOR", | ||
| self._make_integration_point_tensor_entries(expected_strain, num_elements=2, num_integration_points_per_element=1), | ||
| time, precision_places) | ||
| node_ids = sorted(expected_displacement) |
There was a problem hiding this comment.
Here, I'm getting a bit confused. Why would the node IDs be equal to the sorted expected displacements? I would have expected something like (since the node IDs are the keys in the map with the expected displacements, right?):
| node_ids = sorted(expected_displacement) | |
| node_ids = sorted(expected_displacement.keys()) |
I can guess why the code works, but I'm not 100% sure. Perhaps iterating over a map yields the keys? If yes, then I would prefer the more explicit expression, i.e. by adding .keys(). Thank you.
I'm also wondering whether the node IDs need to be sorted or not. It seems to me that the code would also work if the node IDs are not sorted. Or am I overlooking something?
There was a problem hiding this comment.
From the python sorting techniques it works like the following example:
sorted({1: 'D', 2: 'B', 3: 'B', 4: 'E', 5: 'A'})
[1, 2, 3, 4, 5]
They do not need to be sorted necessarily, but it was just a way to get the keys. I will add the .keys() for clarity. I can also do just expected_displacement.keys() without sorted. that returns a dict object then instead of a list but it also works here. Please let me know if that is even more clear.
There was a problem hiding this comment.
Okay maybe not a real dict object but I don't know what to call it.
Just expected_displacement.keys()
returns: dict_keys([1, 2, 3, 4, 5, 6, 7, 8, 9])
| return {key: [row[value] for value in values] | ||
| for key, row in get_values_from_csv(csv_filepath, keys, values).items()} | ||
|
|
||
| def get_values_from_csv_grouped(csv_filepath, grouping_keys, entry_keys, values): |
There was a problem hiding this comment.
I find this function a bit difficult to read. But I don't have a better suggestion yet. Perhaps the only thing I can think of is to rename the last three arguments as suggested before.
I added a function to read values from a csv to the test helper.
The function 'get_values_from_csv' gets the float values corresponding to the keys. This is a general use and can be also used for the CROW case script.
The function 'get_values_from_csv_as_vectors' gets the values corresponding to the keys as a vector. This way it is possible to assert entire cauchy stress tensors or strain tensors at once.
The last function 'get_values_from_csv_grouped' allows to get values grouped. This is used for example if you have multiple phases and want to store all the data from different phases in the same csv file. The function now returns an array, but maybe we would like to have it also available to return a float value like 'get_values_from_csv'.
I implemented the new functions on the test_element_lab.py to test their functionality.