Posts: 10
Threads: 2
Joined: Jul 2017
Hi, right now I'm working on a python dilution calculator. Using the dilution equation
C1V1 = C2V2 I've made this simple protocol that works:
#enter in your values
initial_concentration = input("Enter initial concentration")
initial_concentration = float(initial_concentration)
final_concentration = input("Enter final concentration")
final_concentration = float(final_concentration)
final_volume = input("Enter final volume")
final_volume = float(final_volume)
#this values volume using the equation C1V1 = C2V2
initial_volume = (final_concentration * final_volume) /
initial_concentration
print("Initial volume:", initial_volume) I was wondering if there was a way I could adjust my code so it could read a large table of initial/final concentrations and final volumes to calculate many different initial volumes.
Somehow it could read a table of values - if that makes sense. Here's an alternative version of the simple code (this doesn't work - but as an example in the code they enter in specific values - furthermore, any way to get this to work?):
#enter in your initial concentration
ic = 4
#enter in your final concentration
fc = 5
#enter in your final volume
fv = 3
(fc * fv) / fc = iv
iv = inital volume
print("initial volume:",iv) I'm quite new to coding so any help would be great!
Posts: 2,125
Threads: 11
Joined: May 2017
Yes, for example with a csv file.
dilution.csv
ic,fc,fv
1,2,3
3,4,5
6,7,8
2,1,5
5,3,6
3,6,3
4,6,3
5,4,2
7,5,3
2,4,6
1.1,2.4,4.7
3.14,3.3,4.5
import csv
def calc_inital_volume(ic, fc, fv):
return (fc * fv) / fc
def calc_csv(file):
with open(file) as fd:
reader = csv.reader(fd)
head = next(reader)
#print('Header:', ' '.join(head))
for row in reader:
ic, fc, fv = map(float, row)
iv = calc_inital_volume(ic, fc, fv)
print('IC: {:<5}FC: {:<5}FV: {:<5}IV: {}'.format(ic, fc, fv, iv))
if __name__ == '__main__':
calc_csv('dilution.csv') I'm using the With-Statement.
Read the documentation about csv which is inside the Python stdlib.
Inside the print function I use string formatting.
I know the upcomming question. How to write the results into a new csv-file.
With a little modification, you can convert the function into a generator and iterate outside over the generator.
def calc_csv(file):
with open(file) as fd:
reader = csv.reader(fd)
head = next(reader)
#print('Header:', ' '.join(head))
for row in reader:
ic, fc, fv = map(float, row)
iv = calc_inital_volume(ic, fc, fv)
#print('IC: {:<5}FC: {:<5}FV: {:<5}IV: {}'.format(ic, fc, fv, iv))
yield ic, fc, fv, iv
if __name__ == '__main__':
for row in calc_csv('dilution.csv'):
print(row) Now you've much to read. Have a nice day.
Posts: 10
Threads: 2
Joined: Jul 2017
Hi, firstly - thank you for such a detailed response, it really helps make everything clear! I just want to make sure I'm clear about rows/columns.
I've identified what I want to do in reading CSV files. I found some questions online answering similar things but none of the answers made too much sense to me.
Ideally - what would happen is that I would have a csv file with 4 columns and any number of rows. The values in the column would belong to initial/final concentration and final volume. The fourth column would be blank, belonging to initial volume, which the code would solve. I just want to make sure I'm not mixing up rows/columns as I am unsure how rows comes to play in transferring into from CSV files to act as values for variables.
I've set up the code already (in original post) to solve for initial volume, but I'm having trouble figuring out how to translate CSV columns to act as the values for variables in the code- your code has helped a lot, but I'm drawing a blank where to start with the initial code (first one) as I think I'd like to stay with that one as it is very straight forward.
Posts: 2,125
Threads: 11
Joined: May 2017
Rows and columns as table:
row0 | column0,column1,column2,column3
row1 | column0,column1,column2,column3
row2 | column0,column1,column2,column3
row3 | column0,column1,column2,column3
row4 | column0,column1,column2,column3 This structure as a list with list in Python:
rows = [['column0', 'column1', 'column2', 'column3'],
['column0', 'column1', 'column2', 'column3'],
['column0', 'column1', 'column2', 'column3'],
['column0', 'column1', 'column2', 'column3'],
['column0', 'column1', 'column2', 'column3']] When you iterate over this list, you're iterating row for row in rows.
The csv reader reads for each iteration a row, then it's using the delimiter=',',
which is the default in csv, to split the values. You'll get a list back,
which are the columns.
if __name__ == '__main__':
with open('dilution_out.csv', 'w') as fd_out:
writer = csv.writer(fd_out)
writer.writerow(['ic', 'fc', 'fv', 'iv'])
# this write the first row
for row in calc_csv('dilution.csv'):
# row = (ic, fc, fv, iv)
# this comes from the generator
print(row)
writer.writerow(row)
# the method writerow needs as argument
# an iterabe (list, tuple, set, etc.)
# then it joins the text with , Don't use str for writing rows.
writer.writerow('Hello World') Then the result is:
Output: H,e,l,l,o, ,W,o,r,l,d
Posts: 10
Threads: 2
Joined: Jul 2017
To really simplify it - would something like this also work? I keep receiving a EOF while scanning triple-quoted string literal.
import csv
f = open('dilutions.csv')
#to pull data from a CSV file you must use the reader function
csv_f = csv.reader(f)
#for is the way to itierate over a loop
for row in csv_f:
initial_concentration = input("Enter initial concentration")
initial_concentration = float(initial_concentration)
final_concentration = input("Enter final concentration")
final_concentration = float(final_concentration)
final_volume = input("Enter final volume")
final_volume = float(final_volume)
initial_volume = (final_concentration * final_volume) / initial_concentration
print("Initial volume:", initial_volume)
f.close()
Posts: 2,125
Threads: 11
Joined: May 2017
Please post the source of dilutions.csv and the stacktrace.
Posts: 10
Threads: 2
Joined: Jul 2017
I'm not sure what a stacktrace is but I was just using a simple, random dilution cvs I made in a few moments from yours-
With
ic, fc, fv
1, 2, 3
3, 4, 5
6, 7, 8
2, 1, 5
5, 3, 6
Posts: 2,125
Threads: 11
Joined: May 2017
The answer to your question before. No, this won't work.
You are iterating over the content of the csv file. But you are doing nothing with row.
But I don't understand the part with the triple-quoted string literal. Where is the place with a triple-quoted string literal?
Posts: 1,298
Threads: 38
Joined: Sep 2016
(Aug-01-2017, 08:45 PM)KatherineHov Wrote: I'm not sure what a stacktrace is ...
I believe he his referring to the actual error code you are getting, in it's entirety. May take the form something like this:
Error: >>> print("Hello World)
File "<stdin>", line 1
print("Hello World)
^
SyntaxError: EOL while scanning string literal
>>>
Also, in your last example, you are opening the file to "read", yet are asking a lot of questions as if you mean to "write" the variables at some point.
One final question, do you truly want your data (in your sample cvs file) to be prefaced by a "space"? Normally, there is no space between the delimiter and the data.
If it ain't broke, I just haven't gotten to it yet.
OS: Windows 10, openSuse 42.3, freeBSD 11, Raspian "Stretch"
Python 3.6.5, IDE: PyCharm 2018 Community Edition
|