Skip to content

Commit 85744b5

Browse files
authored
Merge pull request #13 from PascalGitz/pascals_playground
Pascals playground
2 parents 5bcfdf3 + 112b0e2 commit 85744b5

8 files changed

Lines changed: 354 additions & 128 deletions

File tree

engicalc.egg-info/PKG-INFO

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ Requires-Python: >=3.6
1212
Description-Content-Type: text/markdown
1313
Requires-Dist: numpy
1414
Requires-Dist: sympy
15-
Requires-Dist: IPython
1615

1716
# EngiCalc
1817

@@ -31,7 +30,4 @@ Once the calculations are complete, they can be output as Word files using Quart
3130

3231
## Installation
3332

34-
To install EngiCalc, use pip:
35-
36-
```bash
37-
pip install engicalc
33+
Install from this Repo

engicalc.egg-info/SOURCES.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ setup.py
33
engicalc/__init__.py
44
engicalc/concrete.py
55
engicalc/main.py
6+
engicalc/materials.py
67
engicalc/output.py
8+
engicalc/units.py
79
engicalc.egg-info/PKG-INFO
810
engicalc.egg-info/SOURCES.txt
911
engicalc.egg-info/dependency_links.txt

engicalc.egg-info/requires.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
numpy
22
sympy
3-
IPython

engicalc/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1+
from engicalc.output import *
2+
13
import engicalc.concrete
2-
from engicalc.output import put_out, dict_to_markdown_table
3-
from engicalc.materials import Beton
4+
import engicalc.materials
45
import engicalc.units

engicalc/output.py

Lines changed: 139 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,29 @@
11
from IPython.display import display, Markdown, Latex
22
import io
3+
import re
34
from contextlib import redirect_stdout
4-
from sympy import Symbol, latex
5+
from sympy import Symbol, latex, Matrix
56
import numpy as np
7+
from tabulate import tabulate
68

9+
# Define special characters and symbols
10+
special_characters = {
11+
"diam": r"\oslash",
12+
"apos": r"'",
13+
"sum": r"\sum",
14+
"comma": r",",
15+
}
716

8-
def put_out(offset: int = 0, precision: int = 2, rows: int = 3, horizontal: bool = True) -> None:
17+
def parse_cell_variables(offset: int = 0) -> dict:
918
"""
10-
Renders the variables and their values as LaTeX equations in a Jupyter notebook.
19+
Parses the cell history to extract variable names and their corresponding values.
1120
1221
Args:
1322
offset (int): The number of previous cells to include for variable extraction. Defaults to 0.
14-
precision (int): The precision for numerical values. Defaults to 2.
15-
rows (int): Maximum number of equations per row in horizontal display. Defaults to 3.
16-
horizontal (bool): Whether to display equations horizontally or vertically. Defaults to True.
1723
1824
Returns:
19-
None
25+
dict: A dictionary with variable names as keys and their corresponding values from the user namespace.
2026
"""
21-
2227
ipy = get_ipython()
2328
out = io.StringIO()
2429

@@ -34,100 +39,141 @@ def put_out(offset: int = 0, precision: int = 2, rows: int = 3, horizontal: bool
3439
user_ns = ipy.user_ns
3540
variables = {name: user_ns[name] for name in variable_names if name in user_ns}
3641

37-
38-
def format_value(value):
39-
"""Formats the value based on its type."""
40-
if isinstance(value, (int, float)):
41-
return round(value, precision)
42-
elif isinstance(value, np.ndarray):
43-
return np.array2string(np.round(value, precision), separator=",")
44-
elif hasattr(value, "magnitude"):
45-
magnitude = np.round(value.magnitude, precision)
46-
if isinstance(magnitude, np.ndarray):
47-
magnitude_str = np.array2string(magnitude, separator=",")
48-
return f"{magnitude_str} \\ {latex(Symbol(str(value.units)))}"
49-
else:
50-
return f"{magnitude} \\ {latex(Symbol(str(value.units)))}"
51-
else:
52-
return value
42+
return variables
5343

5444

55-
# Format the variables and their values
56-
formatted_vars = {name: format_value(value) for name, value in variables.items()}
5745

58-
if horizontal:
59-
# Horizontal display with aligned '=' signs
60-
var_list = list(formatted_vars.items())
46+
def format_name(name: str, symbols: dict = special_characters) -> str:
47+
"""Formats the input string with specific LaTeX replacements, handles underscores, and converts 'txt_' prefix to plain text."""
48+
49+
# Regex to find words, underscores, and numbers separately
50+
name_parts = re.findall(r'[a-zA-Z]+|_|\d+', name)
51+
52+
result_parts = []
53+
i = 0
6154

62-
# check if there are less variables than rows. This results in clean aligning of the equations
63-
if len(var_list)<rows:
64-
rows = len(var_list)
55+
while i < len(name_parts):
56+
part = name_parts[i]
6557

66-
markdown_str = "$$\n\\begin{aligned}\n"
67-
# Iterate through the variables
68-
for i in range(0, len(var_list), rows):
69-
row = var_list[i : i + rows]
70-
row_str = " \\quad & ".join(
71-
[f"{latex(Symbol(var_name))} & = {value}" for var_name, value in row]
72-
)
73-
# Add placeholders for missing variables in the row
74-
if len(row) < rows & rows!=1:
75-
row_str += " \\quad & " * (rows - len(row)) + " \n"
76-
77-
markdown_str += row_str + " \\\\ \n"
78-
# strip the last space
79-
if markdown_str.endswith(" \\\\ \n"):
80-
markdown_str = markdown_str[:-4]
81-
markdown_str += "\\end{aligned}\n$$"
82-
83-
else:
84-
markdown_str = ""
85-
for var_name, value in formatted_vars.items():
86-
markdown_str += f"$${latex(Symbol(var_name))} = {value}$$\n\n"
87-
88-
display(Markdown(markdown_str))
89-
58+
# Handle the 'sum_' exception
59+
if part == 'sum' and i + 1 < len(name_parts) and name_parts[i + 1] == '_':
60+
result_parts.append(symbols.get(part, part))
61+
i += 1 # Skip the underscore after 'sum'
62+
63+
# Handle the '_strich' exception
64+
elif part == '_' and i + 1 < len(name_parts) and name_parts[i + 1] == 'apos':
65+
result_parts.append(symbols.get(name_parts[i + 1], name_parts[i + 1]))
66+
i += 1 # Skip both underscore and 'strich'
67+
68+
# Replace regular parts using the dictionary
69+
elif part in symbols:
70+
result_parts.append(symbols[part])
71+
72+
# Preserve numbers and non-matching underscores
73+
else:
74+
result_parts.append(part)
75+
76+
i += 1
9077

91-
def dict_to_markdown_table(data: dict) -> str:
92-
if not data:
93-
return ""
94-
95-
# Extract keys and values
96-
items = list(data.items())
97-
rows = []
98-
99-
# Pair items into rows with 4 columns (2 key-value pairs per row)
100-
for i in range(0, len(items), 2):
101-
row = []
102-
for j in range(2):
103-
if i + j < len(items):
104-
key, value = items[i + j]
105-
row.extend([str(key), str(value)])
106-
else:
107-
row.extend(["-", "-"]) # Fill empty cells for incomplete rows
108-
rows.append(row)
109-
110-
# Headers for the 4 columns
111-
headers = ["Bezeichnung", "Wert", "Bezeichnung", "Wert"]
112-
113-
# Calculate column widths
114-
col_widths = [max(len(row[i]) for row in [headers] + rows) for i in range(4)]
78+
# Join all parts back together
79+
name_replaced = ''.join(result_parts)
11580

116-
# Create the markdown table
117-
table = []
81+
# make a symbol out of it
82+
name_replaced = latex(Symbol(name_replaced))
83+
84+
return name_replaced
11885

119-
# Header row
120-
header_row = "| " + " | ".join(headers[i].ljust(col_widths[i]) for i in range(4)) + " |"
121-
table.append(header_row)
86+
def format_value(value, precision: float = 2):
87+
"""Formats the value based on its type."""
88+
if isinstance(value, (int, float)):
89+
return round(value, precision)
12290

123-
# Divider
124-
divider = "| " + " | ".join("-" * col_widths[i] for i in range(4)) + " |"
125-
table.append(divider)
91+
elif isinstance(value, np.ndarray):
92+
# Handle numpy arrays as matrices
93+
rounded_value = np.round(value, precision)
94+
matrix = Matrix(rounded_value.tolist())
95+
return latex(matrix)
12696

127-
# Data rows
128-
for row in rows:
129-
row_str = "| " + " | ".join(row[i].ljust(col_widths[i]) for i in range(4)) + " |"
130-
table.append(row_str)
97+
elif isinstance(value, list):
98+
# Handle lists as vectors
99+
formatted_list = [format_value(item, precision) for item in value]
100+
return formatted_list
131101

132-
return "\n".join(table)
102+
elif hasattr(value, "magnitude"):
103+
# Handle Pint quantities
104+
magnitude = np.round(value.magnitude, precision)
105+
if isinstance(magnitude, np.ndarray):
106+
# Handle numpy arrays of Pint quantities as matrices
107+
magnitude_str = np.array2string(magnitude, separator=",")
108+
return f"{latex(Matrix(magnitude.tolist()))} \\ {latex(Symbol(str(value.units)))}"
109+
else:
110+
# Handle scalar Pint quantities
111+
return f"{magnitude} \\ {latex(Symbol(str(value.units)))}"
112+
else:
113+
return value
114+
115+
def dict_to_markdown_table(dict:dict, symbols: dict= special_characters, precision:int=2, tablefmt: str='pipe'):
116+
# Convert dictionary to list of lists with appropriate headers
117+
formatted_data = [[key, '$'+str(format_value(value, precision))+'$'] for key, value in dict.items()]
118+
headers = ['Bezeichnung', 'Wert']
119+
120+
# Generate the Markdown table
121+
markdown_table = tabulate(formatted_data, headers=headers, tablefmt=tablefmt)
122+
123+
return markdown_table
124+
125+
126+
127+
def put_out(precision: int = 2, offset: int = 0, rows: int = 3, symbols: dict = special_characters, tablefmt:str = 'pipe') -> None:
128+
"""
129+
Renders the variables and their values as LaTeX equations in a Jupyter notebook.
130+
131+
Args:
132+
precision (int): The precision for numerical values. Defaults to 2.
133+
offset (int): The number of previous cells to include for variable extraction. Defaults to 0.
134+
rows (int): Maximum number of equations per row in horizontal display. Defaults to 3.
135+
symbols (dict): Dictionary of symbols for LaTeX formatting.
136+
137+
Returns:
138+
None
139+
"""
140+
# Use the new cell parser function
141+
variables = parse_cell_variables(offset)
142+
143+
144+
formatted_vars = {}
145+
146+
for name, value in variables.items():
147+
if type(value) == dict:
148+
display(Markdown(dict_to_markdown_table(value, precision=precision, tablefmt=tablefmt)))
149+
150+
else:
151+
formatted_vars.update({format_name(name, symbols=symbols): format_value(value, precision=precision)})
152+
153+
# Horizontal display with aligned '=' signs
154+
var_list = list(formatted_vars.items())
155+
156+
if len(var_list) == 0:
157+
return
158+
elif len(var_list) < rows:
159+
rows = len(var_list)
160+
161+
markdown_str = "$$\n\\begin{aligned}\n"
162+
for i in range(0, len(var_list), rows):
163+
row = var_list[i : i + rows]
164+
row_str = " \\quad & ".join(
165+
[f"{var_name} & = {value}" for var_name, value in row]
166+
)
167+
if len(row) < rows and rows != 1:
168+
row_str += " \\quad & " * (rows - len(row)) + " \n"
169+
170+
markdown_str += row_str + " \\\\ \n"
171+
172+
if markdown_str.endswith(" \\\\ \n"):
173+
markdown_str = markdown_str[:-4]
174+
markdown_str += "\\end{aligned}\n$$"
175+
176+
display(Markdown(markdown_str))
177+
178+
133179

engicalc/units.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
# Erstellen eines UnitRegistry-Objekts
88
ureg = UnitRegistry()
9-
ureg.formatter.default_format = "~P"
9+
ureg.formatter.default_format = "~L"
1010

1111
# Definition aller relevanten Einheiten
1212
kg = ureg.kg

setup.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22

33
setup(
44
name='engicalc',
5-
version='0.1.0',
5+
version='v0.0.1',
66
packages=find_packages(),
77
install_requires=[
88
# List your package dependencies here
9-
'numpy',
10-
'sympy',
9+
'numpy>=1.26.4',
10+
'sympy>=1.12.1',
11+
'jupyter>=1.0.0',
12+
'pint @ git+https://github.com/PascalGitz/pint.git',
13+
'tabulate'
1114
],
1215
entry_points={
1316
'console_scripts': [

0 commit comments

Comments
 (0)