Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "Revert "fixed dead volume form and acid concentration calculations"" #192

Merged
merged 1 commit into from
Dec 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion escalate/core/forms/custom_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def get_helper():

class SingleValForm(Form):
value = ValFormField(required=False)
uuid = CharField(widget=HiddenInput)
uuid = CharField(widget=HiddenInput, required=False)


class RobotForm(Form):
Expand Down
59 changes: 33 additions & 26 deletions escalate/core/utilities/calculations.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def conc_to_amount(exp_uuid):
conc_val = conc.nominal_value.value
conc_unit = conc.nominal_value.unit
conc = Q_(conc_val, conc_unit)
mat_type=reagent_material.template.material_type.description
phase = reagent_material.material.phase
if not phase:
raise ValueError(
Expand All @@ -53,6 +54,7 @@ def conc_to_amount(exp_uuid):

input_data[reagent_material] = {
"concentration": conc,
"material_type": mat_type,
"phase": phase,
"molecular weight": mw,
"density": d,
Expand Down Expand Up @@ -180,28 +182,20 @@ def generate_input_f(reagent, MW, density):
return input_data


def calculate_amounts(input_data, target_vol, dead_vol="3000 uL"):
def calculate_amounts(input_data, target_vol, dead_vol="4000 uL"):

"""
Given input data from helper function and target/dead volumes (strings with units),
Given input data dictionary for reagents and target/dead volumes,
returns amounts of each reagent component needed to achieve desired concentrations.
For solids/solutes, amounts will be reported in grams.
For liquid/solvent, amount will be reported in mL.
For liquid/solvent/acid, amount will be reported in mL.

"""

# input_data comes from helper function above
# target_vol and dead_vol must be input as strings with units

amounts = {}
amounts = {}
exact_amounts = {} #use this to store exact values for more precise calculations

# convert volumes to mL and store in proper Pint format
# mag_t=float(total_vol.split()[0])
# unit_t= str(total_vol.split()[1])

# mag_d=float(dead_vol.split()[0])
# unit_d=str(dead_vol.split()[1])

vol = Q_(target_vol).to(units.ml)
dead = Q_(dead_vol).to(units.ml)
total_vol = vol + dead
Expand All @@ -214,22 +208,35 @@ def calculate_amounts(input_data, target_vol, dead_vol="3000 uL"):
* val["molecular weight"]
)
# convert concentration to moles to mass
exact_amounts[key] = grams
amounts[key] = round(grams, 2)

for substance, amount in amounts.items(): # for all solids
total_vol -= amount / input_data[substance]["density"] # find the volume
# find the volume. subtract from total volume - this is how much liquid will be needed

for key, val in input_data.items():
if val["phase"] == "liquid":
if val["material_type"]=="acid": # for the acids
neat=((100/val["molecular weight"])/ (100/val['density'])).to(units.mol/units.ml) #concentration of neat (pure) acid
vol= total_vol* val["concentration"].to(units.mol / units.ml)/neat #dilution
exact_amounts[key]=vol
amounts[key]=round(vol, 2)

for substance, amount in exact_amounts.items():
# for solids
if input_data[substance]["phase"]=='solid':
total_vol -= amount / input_data[substance]["density"] # find the volume and subtract from total

#for acids
elif input_data[substance]["phase"]=='liquid':
total_vol -= vol # find the volume and subtract from total

for key, val in input_data.items():
if val["phase"] == "liquid": # for the solvent(s)
if "volume fraction" in val.keys(): # if there is more than one solvent
amounts[key] = round(
total_vol * val["volume fraction"], 2
) # amount is a fraction of the remaining available volume
else: # if there's just one solvent
amounts[key] = round(
total_vol, 2
) # amount is the remaining available volume
if val["phase"] == "liquid":
if val["material_type"]!="acid": #for the solvent(s)
if "volume fraction" in val.keys(): # if there is more than one solvent
amounts[key] = round(
total_vol * val["volume fraction"], 2
) # amount is a fraction of the remaining available volume
else: #if there is just one solvent
amounts[key] = round(total_vol, 2) # amount is the remaining available volume

"""
for key, val in amounts.items(): #convert amounts from Pint format to strings with val and unit
Expand Down
18 changes: 14 additions & 4 deletions escalate/core/views/experiment/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -621,9 +621,18 @@ def process_robot_formsets(self, exp_uuid, request, context):
for reagent_formset in formsets:
if reagent_formset.is_valid():
vector = self.save_forms_reagent(reagent_formset, experiment_copy_uuid, exp_concentrations)
#exp_concentrations = prepare_reagents(
#reagent_formset, exp_concentrations
#)
#try:
exp_concentrations = prepare_reagents(
reagent_formset, exp_concentrations
)
#except TypeError as te:
# messages.error(request, str(te))

dead_volume_form = SingleValForm(request.POST, prefix="dead_volume")
if dead_volume_form.is_valid():
dead_volume = dead_volume_form.cleaned_data['value']
else:
dead_volume = None

# post reaction parameter form
# get label here and get form out of label, use label for description
Expand Down Expand Up @@ -937,7 +946,8 @@ def process_automated_formsets(self, request: HttpRequest, context: dict[str, An
# Save dead volumes should probably be in a separate function
dead_volume_form = SingleValForm(request.POST, prefix="dead_volume")
if dead_volume_form.is_valid():
dead_volume = dead_volume_form.value
dead_volume=dead_volume_form.cleaned_data['value']
#dead_volume = dead_volume_form.value
else:
dead_volume = None

Expand Down