Skip to content

Commit

Permalink
Merge pull request #165 from RangamaniLabUCSD/emmetfrancis/latex-tables
Browse files Browse the repository at this point in the history
Fixes to Latex table formatting
  • Loading branch information
finsberg authored May 11, 2024
2 parents 329cc93 + 75bbd76 commit d4dd39a
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 53 deletions.
4 changes: 2 additions & 2 deletions examples/example3/example3_withaxisymm.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@
" \"final_t\": 1,\n",
" \"initial_dt\": 0.01,\n",
" \"time_precision\": 6,\n",
" \"attempt_timestep_restart_on_divergence\": True\n",
" # \"attempt_timestep_restart_on_divergence\": True\n",
" }\n",
")\n",
"config_cur.flags.update({\"axisymmetric_model\": True})"
Expand Down Expand Up @@ -627,7 +627,7 @@
" \"final_t\": 1,\n",
" \"initial_dt\": 0.01,\n",
" \"time_precision\": 6,\n",
" \"attempt_timestep_restart_on_divergence\": True,\n",
" # \"attempt_timestep_restart_on_divergence\": True,\n",
" }\n",
" )\n",
" config_cur.flags.update({\"axisymmetric_model\": True})\n",
Expand Down
9 changes: 6 additions & 3 deletions smart/mesh_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -1438,16 +1438,19 @@ def load_mesh(
if extra_keys is None:
extra_keys = []

if not pathlib.Path(filename).is_file():
if isinstance(filename, str):
filename = pathlib.Path(filename)

if not filename.is_file():
raise FileNotFoundError(f"File {filename} does not exists")

if mesh is None:
mesh = d.Mesh(comm)

with d.HDF5File(comm, pathlib.Path(filename).with_suffix(".h5").as_posix(), "r") as hdf5:
with d.HDF5File(comm, filename.with_suffix(".h5").as_posix(), "r") as hdf5:
hdf5.read(mesh, "/mesh", False)

dim = mesh.geometric_dimension()
dim = mesh.topology().dim() # geometric_dimension()
mf_cell = d.MeshFunction("size_t", mesh, dim)
mf_facet = d.MeshFunction("size_t", mesh, dim - 1)
subdomains = []
Expand Down
12 changes: 11 additions & 1 deletion smart/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,12 @@ def _init_2_1_reactions_to_symbolic_strings(self):
raise ValueError(
"Reaction %s does not seem to have an associated equation" % reaction.name
)
if reaction.eqn_f_str == "":
reaction.eqn_str = f"-{reaction.eqn_r_str}"
elif reaction.eqn_r_str == "":
reaction.eqn_str = f"{reaction.eqn_f_str}"
else:
reaction.eqn_str = f"{reaction.eqn_f_str}-{reaction.eqn_r_str}"

def _init_2_2_check_reaction_validity(self):
"""Confirms that all reactions have parameters/species defined"""
Expand Down Expand Up @@ -986,7 +992,11 @@ def _init_4_7_set_initial_conditions(self):
# restrict to specified subdomain
u_cur = self.cc[species.compartment_name].u[ukey]
u_new = create_restriction(u_cur, species.subdomain_data, species.subdomain_val)
u_cur.assign(u_new)
values = u_cur.vector().get_local()
values_new = u_new.vector().get_local()
values[species.dof_map] = values_new[species.dof_map]
u_cur.vector().set_local(values)
u_cur.vector().apply("insert")

def _init_5_1_reactions_to_fluxes(self):
"""Convert reactions to flux objects"""
Expand Down
100 changes: 53 additions & 47 deletions smart/model_assembly.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,8 @@ def print_to_latex(
self,
properties_to_print=None,
max_col_width=None,
sig_figs=2,
return_df=True,
sig_figs=3,
return_df=False,
):
"""
Print object properties in latex format.
Expand All @@ -242,7 +242,33 @@ def print_to_latex(

for row in range(df.shape[0]):
for col in range(df.shape[1]):
if isinstance(df.iat[row, col], str):
if df.columns[col] == "eqn_str":
cur_str = df.iat[row, col]
cur_str = "$" + cur_str + "$"
cur_str = cur_str.replace("**", "^")
idx = 0
while idx < len(cur_str):
if cur_str[idx] == "_":
cur_str = cur_str[0 : idx + 1] + "{" + cur_str[idx + 1 :]
isMath = False
testIdx = idx + 2
while not isMath:
if not (cur_str[testIdx].isalnum() or cur_str[testIdx] == "_"):
if cur_str[testIdx] == "*":
cur_str = cur_str[0:testIdx] + "} " + cur_str[testIdx + 1 :]
else:
cur_str = cur_str[0:testIdx] + "}" + cur_str[testIdx:]
isMath = True
else:
testIdx += 1
idx = testIdx + 2
elif cur_str[idx] == "*":
cur_str = cur_str[0:idx] + " " + cur_str[idx + 1 :]
idx += 1
else:
idx += 1
df.iloc[row, col] = cur_str
elif isinstance(df.iat[row, col], str):
cur_str = df.iat[row, col]
if "_" in cur_str:
df.iloc[row, col] = cur_str.replace("_", "\_")
Expand All @@ -259,23 +285,23 @@ def print_to_latex(
new_list[i] = "`"
cur_str = "".join(new_list)
df.iloc[row, col] = cur_str
for col in df.columns:
# Convert quantity objects to unit
if isinstance(df[col].iloc[0], pint.Quantity):
# if tablefmt=='latex':
df[col] = df[col].apply(lambda x: f"${x:0.{sig_figs}e~Lx}$")

if col == "idx":
df = df.drop("idx", axis=1)
# Convert quantity objects to unit
elif isinstance(df.iat[row, col], pint.Quantity):
x = df.iat[row, col]
if isinstance(x.magnitude, str):
df.iloc[row, col] = f"{x:s~P}"
else:
df.iloc[row, col] = f"${x:0.{sig_figs}e~Lx}$"

for col in df.columns:
if "_" in col:
df = df.rename(columns={col: col.replace("_", "\_")})

if return_df:
return df
else:
with pandas.option_context("max_colwidth", 1000):
logger.info(df.to_latex(escape=False, longtable=True, index=False))
logger.info(df.to_latex(escape=False, longtable=True, index=True))

def get_pandas_dataframe_formatted(
self,
Expand Down Expand Up @@ -326,11 +352,14 @@ def print(
)

# # Change certain df entries to best format for printing
for col in df.columns:
# Convert quantity objects to unit
if isinstance(df[col].iloc[0], pint.Quantity):
# if tablefmt=='latex':
df[col] = df[col].apply(lambda x: f"{x:0.{sig_figs}e~P}")
for row in range(df.shape[0]):
for col in range(df.shape[1]):
if isinstance(df.iat[row, col], pint.Quantity):
x = df.iat[row, col]
if isinstance(x.magnitude, str):
df.iloc[row, col] = f"{x:s~P}"
else:
df.iloc[row, col] = f"{x:0.{sig_figs}e~P}"

# print to file
if filename is None:
Expand Down Expand Up @@ -447,7 +476,7 @@ def __init__(self):

self.properties_to_print = [
"_quantity",
"is_time_dependent",
# "is_time_dependent",
"sym_expr",
"notes",
"group",
Expand Down Expand Up @@ -760,8 +789,7 @@ def __init__(self):
self.properties_to_print = [
"compartment_name",
"_Diffusion",
"initial_condition",
"concentration_units",
"_Initial_Concentration",
]

def print(
Expand All @@ -774,33 +802,9 @@ def print(
for s in self:
s.D_quantity
s.latex_name
s.initial_condition_quantity
super().print(tablefmt, self.properties_to_print, filename, max_col_width)

def print_to_latex(
self,
properties_to_print=None,
max_col_width=None,
sig_figs=2,
return_df=False,
):
properties_to_print = ["_latex_name"]
properties_to_print.extend(self.properties_to_print)
df = super().print_to_latex(properties_to_print, max_col_width, sig_figs, return_df=True)
# fix dof_index
for col in df.columns:
if col == "dof_index":
df[col] = df[col].astype(int)
# fix name
# get the column of df that contains the name
# this can be more robust
# df.columns

if return_df:
return df
else:
with pandas.option_context("max_colwidth", 1000):
logger.info(df.to_latex(escape=False, longtable=True, index=False))


@dataclass
class Species(ObjectInstance):
Expand Down Expand Up @@ -841,7 +845,6 @@ class Species(ObjectInstance):
def to_dict(self):
"Convert to a dict that can be used to recreate the object."
keys_to_keep = [
"name",
"initial_condition",
"concentration_units",
"D",
Expand Down Expand Up @@ -1139,7 +1142,7 @@ class ReactionContainer(ObjectContainer):
def __init__(self):
super().__init__(Reaction)

self.properties_to_print = ["lhs", "rhs", "eqn_f_str", "eqn_r_str"]
self.properties_to_print = ["lhs", "rhs", "eqn_str", "topology"]

def print(
self,
Expand Down Expand Up @@ -1217,6 +1220,8 @@ class Reaction(ObjectInstance):
track_value: bool = False
eqn_f_str: str = ""
eqn_r_str: str = ""
eqn_str: str = ""
topology: str = ""
group: str = ""
axisymm: bool = False
has_subdomain: bool = False
Expand All @@ -1235,6 +1240,7 @@ def to_dict(self):
"track_value",
"eqn_f_str",
"eqn_r_str",
"eqn_str",
"group",
"axisymm",
]
Expand Down

0 comments on commit d4dd39a

Please sign in to comment.