I am running a watershell ptraj file on a coordinate file to find distances of salt ions to a specific atom. I have made the watershell command and I am attempting to write a python code that can run the watershell for a range of values. the command is as follows:
for xi in range(0, 25, 0.2):
x = xi
y = xi + 0.2
file = 'file1'+str(xi)+'.dat'
command = 'watershell :141-182#C1 output.dat lower xi upper y :183-392#Na+'
print(x,y)
I am getting TypeError: 'float' object cannot be interpreted as integer.
The range function won't take a float as a step value; instead you have to use an int. You can get around this by using a multiplier and then dividing when you need to make use of your variable, try something like this:
for xi in range(0, 250, 2):
x = round(xi / 10.0,1)
y = round(xi / 10.0,1) + 0.2
file = 'file1'+str(xi)+'.dat'
command = 'watershell :141-182#C1 output.dat lower xi upper y :183-392#Na+'
print(x,y)
The expression range(0, 25, 0.2) is illegal. The step has to be an integer, so 0.2 is not allowed. I guess you'll have to use a for loop.
Related
This is the whole code of the function I defined
def solve(eq, var=('x', 'y')):
import re
var_re = re.compile(r'(\+|\-)\s*(\d*)\s*\*?\s*(x|y)')
const_re = re.compile(r'(\+|\-)\s*(\-?\d+)$')
constants, eqns, coeffs, default = [],[], {'x': [], 'y': []}, {'': '1'}
for e in eq.split(';'):
eq1 = e.replace("="," - ").strip()
if not eq1.startswith('-'):
eq1 = '+' + eq1
eqns.append(eq1)
var_eq1, var_eq2 = map(var_re.findall, eqns)
constants = [-1*int(x[0][1]) for x in map(const_re.findall, eqns)]
[coeffs[x[2]].append(int((x[0]+ default.get(x[1], x[1])).strip())) for x in (var_eq1 + var_eq2)]
ycoeff = coeffs['y']
xcoeff = coeffs['x']
# Adjust equations to take out y and solve for x
if ycoeff[0]*ycoeff[1] > 0:
ycoeff[1] *= -1
xcoeff[0] *= ycoeff[1]
constants[0] *= -1*ycoeff[1]
else:
xcoeff[0] *= -1*ycoeff[1]
constants[0] *= ycoeff[1]
xcoeff[1] *= ycoeff[0]
constants[1] *= -1*ycoeff[0]
# Obtain x
xval = sum(constants)*1.0/sum(xcoeff)
# Now solve for y using value of x
z = eval(eqns[0],{'x': xval, 'y': 1j})
yval = -z.real*1.0/z.imag
return (xval, yval)
I tried using multiple ways to make the function solve input like
equation1 = int(input(("Enter the first equation: "))
num1 = int(input("Enter the second equation: "))
print (solve(equation1; num1))
with and without int and
num3 = input("Enter both equations using semicolon between them: ")
solve('num3')
and
b = int(input(("Enter both equations using semicolon between them: "))
print("The prime factors of", b, "are", solve(b))
but error messages like
Traceback (most recent call last):
File "C:/Users/ABDELRAHMANSHERIF/ujn.py", line 45, in <module>
solve('num3')
File "C:/Users/ABDELRAHMANSHERIF/ujn.py", line 15, in solve
var_eq1, var_eq2 = map(var_re.findall, eqns)
ValueError: not enough values to unpack (expected 2, got 1)
and some other error messages
so how can I put the input function where the user enters the equations and it gets solved. I know I can just use the solve function in the shell but its a part of a bigger project.
The function solves simultaneous equations by the way.
The function that you use is designed to solve a system of linear equations with two variables x and y. The syntax that you need to use is the following "first_equation;second_equation" :
equation1 = "2*x+3*y=6;4*x+9*y=15"
print(solve(equation1))
If you run it, you will have the result : (1.5, 1.0)
In order to have well written function, the best is to add docstring (or doctest) after the name of your function in order to know how to call it.
I'm trying to implement a system for encryption similar to Shamir's Secret Sharing using Python. Essentially, I have code that will generate a list of points that can be used to find a password at the y-intercept of the gradient formed by these points. The password is a number in ASCII (using two digits per ASCII character), thus is gets to be a pretty big number with larger passwords. For example, the password ThisIsAPassword will generate a list of points that looks like this:
x y
9556 66707086867915126140753213946756441607861037300900
4083 28502040182447127964404994111341362715565457349000
9684 67600608880657662915204624898507424633297513499300
9197 64201036847801292531159022293017356403707170463200
To be clear, these points are generated upon a randomly chosen slope (this is fine since it's the y-intercept that matters).
The problem arises in trying to make a program to decode a password. Using normal math, Python is unable to accurately find the password because of the size of the numbers. Here's the code I have:
def findYint(x,y):
slope = (y[1] - y[0]) / (x[1] - x[0])
yint = int(y[0] - slope * x[0])
return yint
def asciiToString(num):
chars = [num[i:i+3] for i in range(0, len(num), 3)]
return ''.join(chr(int(i)) for i in chars)
def main():
fi = open('pass.txt','r')
x,y = [], []
for i in fi:
row = i.split()
x.append(int(row[0]))
y.append(int(row[1]))
fi.close()
yint = findYint(x,y)
pword = asciiToString(str(yint))
print(pword)
main()
Output (with the password "ThisIsAPassword"):
͉)3 ǢΜĩũć»¢ǔ¼
Typically my code will work with shorter passwords such as "pass" or "word", but the bigger numbers presumably aren't computed with the exact accuracy needed to convert them into ASCII. Any solutions for using either precise math or something else?
Also here's the code for generating points in case it's important:
import random
def encryptWord(word):
numlist = []
for i in range(len(word)):
numlist.append(str(ord(word[i])).zfill(3))
num = int("".join(numlist))
return num
def createPoints(pwd, pts):
yint = pwd
gradient = pwd*random.randint(10,100)
xvals = []
yvals = []
for i in range(pts):
n = random.randint(1000,10000)
xvals.append(n)
yvals.append(((n) * gradient) + pwd)
return xvals, yvals
def main():
pword = input("Enter a password to encrypt: ")
pword = encryptWord(pword)
numpoints = int(input("How many points to generate? "))
if numpoints < 2:
numpoints = 2
xpts, ypts = createPoints(pword, numpoints)
fi = open("pass.txt","w")
for i in range(len(xpts)):
fi.write(str(xpts[i]))
fi.write(' ')
fi.write(str(ypts[i]))
fi.write('\n')
fi.close()
print("Sent to file (pass.txt)")
main()
As you may know, Python's built-in int type can handle arbitrarily large integers, but the float type which has limited precision. The only part of your code which deals with numbers that aren't ints seems to be this function:
def findYint(x,y):
slope = (y[1] - y[0]) / (x[1] - x[0])
yint = int(y[0] - slope * x[0])
return yint
Here the division results in a float, even if the result would be exact as an int. Moreover, we can't safely do integer division here with the // operator, because slope will get multiplied by x[0] before the truncation is supposed to happen.
So either you need to do some algebra in order to get the same result using only ints, or you need to represent the fraction (y1 - y0) / (x1 - x0) with an exact non-integer number type instead of float. Fortunately, Python's standard library has a class named Fraction which will do what you want:
from fractions import Fraction
def findYint(x,y):
slope = Fraction(y[1] - y[0], x[1] - x[0])
yint = int(y[0] - slope * x[0])
return yint
It should be possible to do this only with integer-based math:
def findYint(x,y):
return (y[0] * (x[1] - x[0]) - (y[1] - y[0]) * x[0]) // (x[1] - x[0])
This way you avoid the floating point arithmetic and the precision constraints it has.
Fractions, and rewriting for all integer math are good.
For truly large integers, you may find yourself wanting https://pypi.org/project/gmpy/ instead of the builtin int type. I've successfully used it for testing for large primes.
Or if you really do want numbers with a decimal point, maybe try decimal.Decimal("1") - just for example.
I have this Fortran program for compute equivalent width of spectral lines
i hope to find help for write python code to do same algorithm (input file contain tow column wavelength and flux)
PARAMETER (N=195) ! N is the number of data
IMPLICIT DOUBLE PRECISION (A-H,O-Z)
DIMENSION X(N),Y(N)
OPEN(1,FILE='halpha.dat')
DO 10 I=1,N
READ(1,*)X(I),Y(I)
WRITE(*,*)X(I),Y(I)
10 CONTINUE
CALL WIDTH(X,Y,N,SUM)
WRITE(*,*)SUM
END
c-----------------------------------------
SUBROUTINE WIDTH(X,Y,N,SUM)
PARAMETER (NBOD=20000)
IMPLICIT DOUBLE PRECISION (A-H,O-Z)
DIMENSION X(NBOD),Y(NBOD)
SUM=0.D0
DO I=2,N
SUM=SUM+(X(I-1)-X(I))*((1.-Y(I-1))+(1.-Y(I)))
C WRITE(*,*)SUM
END DO
SUM=0.5*dabs(SUM)
RETURN
END
Here's a fairly literal translation:
def main():
N = 195 # number of data pairs
x, y = [0 for i in xrange(N)], [0 for i in xrange(N)]
with open('halpha.dat') as f:
for i in xrange(N):
x[i], y[i] = map(float, f.readline().split())
print x[i], y[i]
sum = width(x, y, N)
print sum
def width(x, y, N):
sum = 0.0
for i in xrange(1, N):
sum = sum + (x[i-1] - x[i]) * ((1. - y[i-1]) + (1. - y[i]))
sum = 0.5*abs(sum)
return sum
main()
However this would be a more idiomatic translation:
from math import fsum # more accurate floating point sum of a series of terms
def main():
with open('halpha.dat') as f: # Read file into a list of tuples.
pairs = [tuple(float(word) for word in line.split()) for line in f]
for pair in pairs:
print('{}, {}'.format(*pair))
print('{}'.format(width(pairs)))
def width(pairs):
def term(prev, curr):
return (prev[0] - curr[0]) * ((1. - prev[1]) + (1. - curr[1]))
return 0.5 * abs(fsum(term(*pairs[i-1:i+1]) for i in range(1, len(pairs))))
main()
I would suggest that a more natural way to do this in Python is to focus on the properties of the spectrum itself, and use your parameters in astropy's specutils.
In particular equivalent_width details are here. For more general info on
specutils, specutils.analysis and its packages follow these links:
specutils top level
and
specutils.analysis
To use this package you need to create a Spectrum1D object, the first component of which will be your wavelength axis and the second will be the flux. You can find details of how to create a Spectrum1D object by following the link in the analysis page (at the end of the third line of first paragraph).
It's a very powerful approach and has been developed by astronomers for astronomers.
I'm taking a Python course at Udacity, and I'm trying to work this out for myself without looking at the answer. Perhaps you can give me a hint for my logic?
Below are the instructions and what I have so far. We haven't learned conditional statements yet, so I can't use those. We've only learned how to assign/print a variable, strings, indexing strings, sub-sequences, and .find. They just introduced the str command in this final exercise.
# Given a variable, x, that stores the
# value of any decimal number, write Python
# code that prints out the nearest whole
# number to x.
# If x is exactly half way between two
# whole numbers, round up, so
# 3.5 rounds to 4 and 2.5 rounds to 3.
# You may assume x is not negative.
# Hint: The str function can convert any number into a string.
# eg str(89) converts the number 89 to the string '89'
# Along with the str function, this problem can be solved
# using just the information introduced in unit 1.
# x = 3.14159
# >>> 3 (not 3.0)
# x = 27.63
# >>> 28 (not 28.0)
# x = 3.5
# >>> 4 (not 4.0)
x = 3.54159
#ENTER CODE BELOW HERE
x = str(x)
dec = x.find('.')
tenth = dec + 1
print x[0:dec]
////
So this gets me to print the characters up to the decimal point, but I can't figure out how to have the computer check whether "tenth" is > 4 or < 5 and print out something according to the answer.
I figured I could probably get far enough for it to return a -1 if "tenth" wasn't > 4, but I don't know how I can get it to print x[0:dec] if it's < 5 and x[0:dec]+1 if it's > 4.
:/
Could someone please give me a nudge in the right direction?
This is a weird restriction, but you could do this:
x = str(x)
dec_index = x.find('.')
tenth_index = dec_index + 1
tenth_place = x[tenth_index] # will be a string of length 1
should_round_up = 5 + tenth_place.find('5') + tenth_place.find('6') + tenth_place.find('7') + tenth_place.find('8') + tenth_place.find('9')
print int(x[0:dec_index]) + should_round_up
What we do is look at the tenths place. Since .find() returns -1 if the argument isn't found, the sum of the .find() calls will be -4 if if the tenths place is 5, 6, 7, 8, or 9 (since one of the .find() calls will succeed and return 0), but will be -5 if the tenths place is 0, 1, 2, 3, or 4. We add 5 to that, so that should_round_up equals 1 if we should round up, and 0 otherwise. Add that to the whole number part, and we're done.
That said, if you weren't subject to this artificial restriction, you would do:
print round(x)
And move on with your life.
judging by the accepted answer you only expects floats so that is pretty trivial to solve:
x = 3.54159
# split on .
a, b = str(x).split(".")
# cast left side to int and add result of test for right side being greater or equal to 5
print(int(a) + (int(b) >= 5))
(int(b) > 5) will be either 1 or 0 i.e True/False so we either add 1 when right side is > .5 or flooring when it's < .5 and adding 0.
If you were doing it mathematically you just need to print(int(x+.5)), anything >= .5 will mean x will be rounded up and floored when it is < .5.
x = 3.54159
# split on .
a, b = str(x).split(".")
# cast left side to int and add result of test for right side being greater or equal to 5
print(int(a) + (int(b[0]) >= 5))
# above code will not work with 3.14567 and the number with having two or more digits after decimal
I think it's easier...
x = x + 0.5
intPart, decPart = str(x).split(".")
print intPart
Examples:
If x = 1, then it will become 1.5 and intPart will be 1.
If x = 1.1, then it will become 1.6 and intPart will be 1.
If x = 1.6, then it will become 2.1 and intPart will be 2.
Note: it will only work for positive numbers.
This code will round numbers to the nearest whole
without using conditionals
You can do it this way
x = 3.54159
x = x + 0.5 # This automatically takes care of the rounding
str_x = str(x) # Converting number x to string
dp = str_x.find('.') # Finding decimal point index
print str_x[:dp] # Printing upto but excluding decimal point
I did the same course at Udacity. solved it using the following code:
y = str(x)
decimal = y.find('.')
y_increment = y[decimal+1:]
print decimal
print y_increment
# Section below finds >5
check5 = y_increment.find('5',0,1)
check6 = y_increment.find('6',0,1)
check7 = y_increment.find('7',0,1)
check8 = y_increment.find('8',0,1)
check9 = y_increment.find('9',0,1)
yes_increment = (check5 + 1) + (check6 + 1) + (check7 + 1) + (check8 + 1) + (check9 + 1)
print check5, check6, check7, check8, check9
#Calculate rounding up
z = x + (yes_increment)
z = str(z)
final_decimal = z.find('.')
print z[:final_decimal]
x = 0.8
y = str(x)
x=x*y
print x, y
Just beginning Python, not looking to fix the code, rather work out how to justify why there is an error. I believe that this attempts to pass a string off as an integer just not sure why you can't do that.
You have this:
x = 0.8 # float
y = str(0.8)
the last line, will be equivalent to
y = "0.8" # string
then, when you do
x = x * y # float * string
you get an error, because it's not possible to multiply a string with a float. But note that you can do that with integers:
x = 3
y = str(6) # y = "6"
this will produce the output "666", because it's multiplying the string "6" 3 times.