Skip to content

Commit

Permalink
Fixed integer only stoichiometries
Browse files Browse the repository at this point in the history
  • Loading branch information
uthpalaherath committed Oct 1, 2024
1 parent 1723975 commit b0dfa06
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 66 deletions.
15 changes: 3 additions & 12 deletions materials/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,31 +66,22 @@ class SystemStoichiometryInline(nested_admin.NestedTabularInline):
model = System_Stoichiometry
extra = 0
verbose_name_plural = "Stoichiometry"
inlines = [StoichiometryElementsInline] # Add StoichiometryElementsInline here
inlines = [StoichiometryElementsInline]

def save_model(self, request, obj, form, change):
# Save the System_Stoichiometry instance
super().save_model(request, obj, form, change)

# Clear existing Stoichiometry_Elements for this stoichiometry
Stoichiometry_Elements.objects.filter(system_stoichiometry=obj).delete()

# Parse the stoichiometry string (e.g., 'C:6,H:12,O:1')
# Updated regex pattern
element_pattern = r"([A-Z][a-z]*):(\d+(?:\.\d+)?)"
elements = re.findall(element_pattern, obj.stoichiometry)

# Create new Stoichiometry_Elements based on the parsed stoichiometry
for element, count in elements:
Stoichiometry_Elements.objects.create(
system_stoichiometry=obj,
element=element,
string_value=str(int(float(count)))
if float(count).is_integer()
else str(count),
string_value=str(count),
float_value=float(count),
)


# SystemAdmin to include the Stoichiometry inline
class SystemAdmin(nested_admin.NestedModelAdmin):
list_display = ("id", "compound_name")
Expand Down
22 changes: 13 additions & 9 deletions materials/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@
from .models import System, System_Stoichiometry, Stoichiometry_Elements
import re


def parse_formula(formula):
tokens = re.findall(r'([A-Z][a-z]?|\(|\)|\d+)', formula)
tokens = re.findall(r"([A-Z][a-z]?|\(|\)|\d+)", formula)
stack = [{}]
i = 0
while i < len(tokens):
token = tokens[i]
if token == '(':
if token == "(":
stack.append({})
i += 1
elif token == ')':
elif token == ")":
top = stack.pop()
i += 1
# Check if there is a multiplier
Expand All @@ -28,7 +29,7 @@ def parse_formula(formula):
multiplier = 1
for element, count in top.items():
stack[-1][element] = stack[-1].get(element, 0) + count * multiplier
elif re.match(r'[A-Z][a-z]?$', token):
elif re.match(r"[A-Z][a-z]?$", token):
element = token
i += 1
if i < len(tokens) and tokens[i].isdigit():
Expand All @@ -41,21 +42,24 @@ def parse_formula(formula):
i += 1
return stack[0]


@receiver(post_save, sender=System)
def create_stoichiometry_entries(sender, instance, created, **kwargs):
if created:
formula = instance.formula
elements_dict = parse_formula(formula)
stoichiometry_str = ",".join([f"{el}:{int(count)}" for el, count in elements_dict.items()])
# Updated regex pattern to match decimals
element_pattern = r"([A-Z][a-z]*)(\d*(?:\.\d+)?)"
elements = re.findall(element_pattern, formula)
stoichiometry_str = ",".join([f"{el}:{count or 1}" for el, count in elements])
stoichiometry = System_Stoichiometry.objects.create(
system=instance, stoichiometry=stoichiometry_str
)
for el, count in elements_dict.items():
for el, count in elements:
Stoichiometry_Elements.objects.create(
system_stoichiometry=stoichiometry,
element=el,
string_value=str(int(count)),
float_value=float(count),
string_value=str(count or "1"),
float_value=float(count) if count else 1.0,
)


Expand Down
95 changes: 50 additions & 45 deletions materials/templates/materials/add_data.html
Original file line number Diff line number Diff line change
Expand Up @@ -671,58 +671,63 @@ <h5 class="modal-title" id="stoichiometryModalLabel">Is this the correct stoichi
var elementsData = {{ elements_json|safe }};
</script>
<script>
function parseFormula(formula) {
const tokens = formula.match(/([A-Z][a-z]?|\(|\)|\d+)/g);
if (!tokens) return {};
const stack = [{}];
let i = 0;
while (i < tokens.length) {
const token = tokens[i];
if (token === '(') {
stack.push({});
i++;
} else if (token === ')') {
const top = stack.pop();
i++;
let multiplier = 1;
if (i < tokens.length && /^\d+$/.test(tokens[i])) {
multiplier = parseInt(tokens[i], 10);
function parseFormula(formula) {
// Updated regex to match decimal numbers
const tokens = formula.match(/([A-Z][a-z]?|\(|\)|\d+(\.\d+)?)/g);
if (!tokens) return {};
const stack = [{}];
let i = 0;
while (i < tokens.length) {
const token = tokens[i];
if (token === '(') {
stack.push({});
i++;
}
for (const [element, count] of Object.entries(top)) {
stack[stack.length - 1][element] = (stack[stack.length - 1][element] || 0) + count * multiplier;
}
} else if (/^[A-Z][a-z]?$/.test(token)) {
const element = token;
i++;
let count = 1;
if (i < tokens.length && /^\d+$/.test(tokens[i])) {
count = parseInt(tokens[i], 10);
} else if (token === ')') {
const top = stack.pop();
i++;
let multiplier = 1;
// Updated to parse decimal multipliers
if (i < tokens.length && /^\d+(\.\d+)?$/.test(tokens[i])) {
multiplier = parseFloat(tokens[i]);
i++;
}
for (const [element, count] of Object.entries(top)) {
stack[stack.length - 1][element] =
(stack[stack.length - 1][element] || 0) + count * multiplier;
}
} else if (/^[A-Z][a-z]?$/.test(token)) {
const element = token;
i++;
let count = 1;
// Updated to parse decimal counts
if (i < tokens.length && /^\d+(\.\d+)?$/.test(tokens[i])) {
count = parseFloat(tokens[i]);
i++;
}
stack[stack.length - 1][element] =
(stack[stack.length - 1][element] || 0) + count;
} else {
i++;
}
stack[stack.length - 1][element] = (stack[stack.length - 1][element] || 0) + count;
} else {
i++;
}
}
return stack[0];
return stack[0];
}

function extractStoichiometry() {
const formulaInput = document.getElementById('id_formula');
if (!formulaInput) {
console.error("Formula input not found");
return;
}
const formula = formulaInput.value;
const elementCounts = parseFormula(formula);
let stoichiometryString = '';
for (const element in elementCounts) {
stoichiometryString += `${element}:${elementCounts[element]}, `;
}
stoichiometryString = stoichiometryString.slice(0, -2);
document.getElementById('stoichiometryOutput').innerText = `${stoichiometryString}`;
$('#stoichiometryModal').modal('show');
const formulaInput = document.getElementById('id_formula');
if (!formulaInput) {
console.error("Formula input not found");
return;
}
const formula = formulaInput.value;
const elementCounts = parseFormula(formula);
let stoichiometryString = '';
for (const element in elementCounts) {
stoichiometryString += `${element}:${elementCounts[element]}, `;
}
stoichiometryString = stoichiometryString.slice(0, -2);
document.getElementById('stoichiometryOutput').innerText = `${stoichiometryString}`;
$('#stoichiometryModal').modal('show');
}

function handleStoichiometryConfirmation(answer){
Expand Down

0 comments on commit b0dfa06

Please sign in to comment.