Plotting: Array dims not matching, Reporting module: LoadCombo not being detected
Describe the bug
Using the example:
Examples/Simple Beam - Point Load.py
There are 2 bugs:
Bug 1
https://github.com/JWock82/Pynite/blob/04ab0745f36913fb4f77849544889d90475a9d0d/Examples/Simple%20Beam%20-%20Point%20Load.py#L57
produces the following error:
Traceback (most recent call last):
File "[removed]", line 57, in <module>
simple_beam.members['M1'].plot_shear('Fy', '1.2D+1.6L')
File "[removed]\site-packages\Pynite\PhysMember.py", line 253, in plot_shear
x_submember, V_submember = submember.shear_array(Direction, n_points, combo_name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "[removed]\site-packages\Pynite\Member3D.py", line 965, in shear_array
return self._extract_vector_results(self.SegmentsZ, x_array, 'shear')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "[removed]\site-packages\Pynite\Member3D.py", line 2278, in _extract_vector_results
return vstack((x_array2, hstack(segment_results)))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "[removed]\site-packages\numpy\_core\shape_base.py", line 292, in vstack
return _nx.concatenate(arrs, 0, dtype=dtype, casting=casting)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: all the input array dimensions except for the concatenation axis must match exactly, but along dimension 1, the array at index 0 has size 10 and the array at index 1 has size 20
Bug 2
I commented out the simple_beam.members['M1'].plot_ items, to try and use the reporting functionality.
https://github.com/JWock82/Pynite/blob/04ab0745f36913fb4f77849544889d90475a9d0d/Examples/Simple%20Beam%20-%20Point%20Load.py#L80
produces the following error:
Traceback (most recent call last):
File "[removed]", line 80, in <module>
Reporting.create_report(simple_beam, output_filepath=Path('./Pynite Report.pdf'), node_table=False, plate_table=False, plate_corner_forces=False, plate_center_forces=False, plate_corner_membrane=False, plate_center_membrane=False)
File "[removed]\site-packages\Pynite\Reporting.py", line 68, in create_report
HTML = template.render(**kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "[removed]\site-packages\jinja2\environment.py", line 1295, in render
self.environment.handle_exception()
File "[removed]\site-packages\jinja2\environment.py", line 942, in handle_exception
raise rewrite_traceback_stack(source=source)
File "[removed]\site-packages\Pynite\Report_Template.html", line 210, in top-level template code
<td>{{ "%.4g" | format(node.RxnFX[combo]) }}</td>
^^^^^^^^^
File "[removed]\site-packages\jinja2\filters.py", line 1043, in do_format
return soft_str(value) % (kwargs or args)
~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
jinja2.exceptions.UndefinedError: dict object has no element <Pynite.LoadCombo.LoadCombo object at [memory address]>
To Reproduce
run Examples/Simple Beam - Point Load.py, with and without the simple_beam.members['M1'].plot_ items.
Expected behavior plotting and reporting
Additional context I'm guessing recent updates have changed the member arrays, affecting plotting. I'm not sure why the jinja report is not accessing load combinations properly, however.
Thanks for the help!
Which version are you using? I recently made changes to address a bug relating to array results.
@JWock82 - Using version 1.1.0
I think I’ve got this issue already fixed in the development version. I’ll issue v1.2.0 here soon which will have this fixed.
Thanks! Is the reporting module error in that update as well? I am not super sure about the source for that one
@JWock82 I found the source of this error, mentioned in the original issue: jinja2.exceptions.UndefinedError: dict object has no element <Pynite.LoadCombo.LoadCombo object at [memory address]>
model.load_combos.values() in this line should be changed to model.load_combos.keys(), as the node values dicts and member value access methods use the load combination keys instead of the actual load combo class objects.
https://github.com/JWock82/Pynite/blob/0a6b11d68d2cc7bf46d16e68ce1856d09c652849/Pynite/Reporting.py#L65
https://github.com/JWock82/Pynite/blob/0a6b11d68d2cc7bf46d16e68ce1856d09c652849/Pynite/Report_Template.html#L285
I also am getting this error on trying to generate a report with the "Example of a basic 2D moment frame with gravity and lateral loads". It also goes away when I switch that line to kwargs['load_combos'] = model.load_combos.keys():
# Import the reporting module
from Pynite import Reporting
from pathlib import Path
# Create the report
Reporting.create_report(frame, output_filepath=Path('./SpaceFrameReport.pdf'))
---------------------------------------------------------------------------
UndefinedError Traceback (most recent call last)
Cell In[17], line 6
3 from pathlib import Path
5 # Create the report
----> 6 Reporting.create_report(frame, output_filepath=Path('./SpaceFrameReport.pdf'))
File ~/miniforge3/envs/pyNiteFEA/lib/python3.11/site-packages/Pynite/Reporting.py:68, in create_report(model, output_filepath, **kwargs)
65 kwargs['load_combos'] = model.load_combos.values()
67 # Create the report HTML using jinja2
---> 68 HTML = template.render(**kwargs)
70 # Convert the HTML to pdf format using PDFKit
71 # Note that wkhtmltopdf must be installed on the system, and included on the system's PATH environment variable for PDFKit to work
72 pdfkit.from_string(HTML, output_filepath, css=path / './MainStyleSheet.css')
File ~/miniforge3/envs/pyNiteFEA/lib/python3.11/site-packages/jinja2/environment.py:1295, in Template.render(self, *args, **kwargs)
1293 return self.environment.concat(self.root_render_func(ctx)) # type: ignore
1294 except Exception:
-> 1295 self.environment.handle_exception()
File ~/miniforge3/envs/pyNiteFEA/lib/python3.11/site-packages/jinja2/environment.py:942, in Environment.handle_exception(self, source)
937 """Exception handling helper. This is used internally to either raise
938 rewritten exceptions or return a rendered traceback for the template.
939 """
940 from .debug import rewrite_traceback_stack
--> 942 raise rewrite_traceback_stack(source=source)
File ~/miniforge3/envs/pyNiteFEA/lib/python3.11/site-packages/Pynite/Report_Template.html:210, in top-level template code()
208 <td>{{ node.name }}</td>
209 <td>{{ combo }}</td>
--> 210 <td>{{ "%.4g" | format(node.RxnFX[combo]) }}</td>
211 <td>{{ "%.4g" | format(node.RxnFY[combo]) }}</td>
212 <td>{{ "%.4g" | format(node.RxnFZ[combo]) }}</td>
File ~/miniforge3/envs/pyNiteFEA/lib/python3.11/site-packages/jinja2/filters.py:1043, in do_format(value, *args, **kwargs)
1038 if args and kwargs:
1039 raise FilterArgumentError(
1040 "can't handle positional and keyword arguments at the same time"
1041 )
-> 1043 return soft_str(value) % (kwargs or args)
UndefinedError: dict object has no element <Pynite.LoadCombo.LoadCombo object at 0x3120f1190>
I recently updated the reporting code. It had not been kept up with the rest of the program. I think this issue has been resolved. Can you verify on your end?
Yes - v 1.5.0 has fixed the reporting problem for that example.
I have however come across similar-looking error for the following example. Should I report this as a new issue?
Examples/Shear Wall - Advanced.py
from Pynite import Reporting
Reporting.create_report(model, format='html', output_filepath='./ModelReport.html')
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
Cell In[28], [line 9](vscode-notebook-cell:?execution_count=28&line=9)
5 print(f'{pynite_get_version("Pynite")}')
7 # Create the report
8 # Reporting.create_report(my_model, output_filepath='./My Report.pdf')
----> [9](vscode-notebook-cell:?execution_count=28&line=9) Reporting.create_report(model, format='html', output_filepath='./ModelReport.html')
File ~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/Pynite/Reporting.py:101, in create_report(model, output_filepath, format, log, **kwargs)
98 kwargs['load_combos'] = model.load_combos.values()
100 # Render HTML from Template
--> [101](https://file+.vscode-resource.vscode-cdn.net/Users/andrew/Documents/GitHub/PyNite_helper/notebooks/~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/Pynite/Reporting.py:101) HTML = template.render(**kwargs)
103 # Check if a PDF file has been requested
104 if format.upper() == 'PDF':
105
106 # Import PDFKit
File ~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/jinja2/environment.py:1295, in Template.render(self, *args, **kwargs)
1293 return self.environment.concat(self.root_render_func(ctx)) # type: ignore
1294 except Exception:
-> [1295](https://file+.vscode-resource.vscode-cdn.net/Users/andrew/Documents/GitHub/PyNite_helper/notebooks/~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/jinja2/environment.py:1295) self.environment.handle_exception()
File ~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/jinja2/environment.py:942, in Environment.handle_exception(self, source)
937 """Exception handling helper. This is used internally to either raise
938 rewritten exceptions or return a rendered traceback for the template.
939 """
940 from .debug import rewrite_traceback_stack
--> [942](https://file+.vscode-resource.vscode-cdn.net/Users/andrew/Documents/GitHub/PyNite_helper/notebooks/~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/jinja2/environment.py:942) raise rewrite_traceback_stack(source=source)
File ~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/Pynite/Report_Template.html:426, in top-level template code()
424 <td>{{ quad.name }}</td>
425 <td>{{ combo.name }}</td>
--> [426](https://file+.vscode-resource.vscode-cdn.net/Users/andrew/Documents/GitHub/PyNite_helper/notebooks/~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/Pynite/Report_Template.html:426) <td>{{ "%.3g" | format(quad.shear(-1, -1, combo.name)[0][0]) }}</td>
427 <td>{{ "%.3g" | format(quad.shear(-1, -1, combo.name)[1][0]) }}</td>
428 <td>{{ "%.3g" | format(quad.moment(-1, -1, combo.name)[0][0]) }}</td>
File ~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/Pynite/Quad3D.py:1034, in Quad3D.shear(self, xi, eta, local, combo_name)
1015 """
1016 Returns the interal shears at any point in the quad element.
1017
(...) 1030 Internal shear force per unit length of the quad element: [[Qx], [Qy]]
1031 """
1033 # Get the plate's local displacement vector
-> [1034](https://file+.vscode-resource.vscode-cdn.net/Users/andrew/Documents/GitHub/PyNite_helper/notebooks/~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/Pynite/Quad3D.py:1034) d = self.d(combo_name)
1036 # Correct the sign convention for x-axis rotation - note that +x bending and +x rotation are opposite in the DKMQ derivation. Hence when correcting d we correct the x terms, but when correcting k we correct the y terms
1037 d[[3, 9, 15, 21], :] *= -1
File ~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/Pynite/Quad3D.py:793, in Quad3D.d(self, combo_name)
788 """
789 Returns the quad element's local displacement vector
790 """
792 # Calculate and return the local displacement vector
--> [793](https://file+.vscode-resource.vscode-cdn.net/Users/andrew/Documents/GitHub/PyNite_helper/notebooks/~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/Pynite/Quad3D.py:793) return self.T() @ self.D(combo_name)
File ~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/Pynite/Quad3D.py:824, in Quad3D.D(self, combo_name)
821 D = np.zeros((24, 1))
823 # Read in the global displacements from the nodes
--> [824](https://file+.vscode-resource.vscode-cdn.net/Users/andrew/Documents/GitHub/PyNite_helper/notebooks/~/miniforge3/envs/pyNiteDev/lib/python3.13/site-packages/Pynite/Quad3D.py:824) D[0, 0] = self.i_node.DX[combo_name]
825 D[1, 0] = self.i_node.DY[combo_name]
826 D[2, 0] = self.i_node.DZ[combo_name]
KeyError: 'Combo 1'