Python too many values to unpack - python

so I want to find distance between two xyz file coordinate using python,
I was given this for example
0.215822, -1.395942, -1.976109
0.648518, -0.493053, -2.101929
In python, I wrote,
f = open('First_Ten_phenolMeNH3+.txt', 'r')
lines = f.readlines()
a = lines[0] #(0.215822, -1.395942, -1.976109)
(x1,y1,z1) = a
b = lines[1] #(0.648518, -0.493053, -2.101929)
(x2,y2,z2) = b
distance = math.sqrt((x1-x2)**2 + (y1-y2)**2 + (z1-z2)**2)
print(distance)
f.close()
I want to use tuple unpacking and to calucalte distance, however, I keep getting too many values to unpack (expected 3), I think it is because of the txt file, Is there any better way I can do it ?? The problem is i need have 5000 coordinate file to sort through, so it will be inefficient to plug in coordinate one by one.
Thank you

You could use this:
from scipy.spatial import distance
from ast import literal_eval
a = literal_eval(lines[0]) #(0.215822, -1.395942, -1.976109)
b = literal_eval(lines[1]) #(0.648518, -0.493053, -2.101929)
dst = distance.euclidean(a, b) #1.009091198622305

you are trying to assign a string to a tuple. try using split() first:
a = lines[0].split() #(0.215822, -1.395942, -1.976109)
(x1,y1,z1) = a
also, this will put strings into x1,x2,x3, you need to convert them to float:
x1 = float(x1)
x2 = float(x2)
x3 = float(x3)

line[0] is a string, as it in a text file. You need to convert it into tuple of floats
x1, y1, z1 = (float(value) for value in line[1:-1].split(', '))

Related

Elliptic curve addition - how to add point coordinates from a file in Python

i'm just a tech newbie learning how ec cryptography works and stumbled into a problem with my python code
i'm testing basic elliptic curve operations like adding points, multiple by G etc, let's say i have
Ax = 0xbc46aa75e5948daa08123b36f2080d234aac274bf62fca8f9eb0aadf829c744a
Ay = 0xe5f28c3a044b1cac54a9b4bf719f02dfae93a0bae73832301e786104f43255a5
A = (Ax,Ay)
f = open('B-coordinates.txt', 'r')
data = f.read()
f.close()
print (data)
B = 'data'
there B-coordinates.txt contains lines like (0xe7e6bd3424a1e92abb45846c82d570f0596850661d1c952f9fe3564567d9b9e8,0x59c9e0bba945e45f40c0aa58379a3cb6a5a2283993e90c58654af4920e37f5)
then i perform basic point addition A+B add(A,B)
so because of B = 'data' i obviously have this error
TypeError: unsupported operand type(s) for -: 'int' and 'str'
and if i add int(data) >
Error invalid literal for int() with base 10: because letters in input (i.e. in points coordinates).
so my question is, please can someone knowledgeable in python and elliptic curve calculations tell me how to add the coordinates of a point so as to bypass these int problems when extracting lines from a file into .py? I will be very grateful for the answer! I've been trying to figure out how to do it right for many hours now, and maybe just goofing off, but please I'll appreciate any hints
You can load B from B-coordinates.txt by evaluating its content as Python code:
B = eval(data)
As the code above leads to arbitrary code execution if you don't trust B-coordinates.txt content. If so, parse the hexadecimal tuple manually:
B = tuple([int(z, 16) for z in data[1:-1].split(',')])
Then to sum A and B in a pairwise manner using native Python 3 and keep a tuple, you can proceed as follows by summing unpacked coordinates (zip) for both tuples:
print(tuple([a + b for (a, b) in zip(A, B)]))
UPDATE:
Assume B-coordinates.txt looks like the following as described by OP author comment:
(0x1257e93a78a5b7d8fe0cf28ff1d8822350c778ac8a30e57d2acfc4d5fb8c192,0x1124ec11c77d356e042dad154e1116eda7cc69244f295166b54e3d341904a1a7)
(0x754e3239f325570cdbbf4a87deee8a66b7f2b33479d468fbc1a50743bf56cc18,0x673fb86e5bda30fb3cd0ed304ea49a023ee33d0197a695d0c5d98093c536683)
...
You can load the Bs from this file by doing:
f = open('B-coordinates.txt', 'r')
lines = f.read().splitlines()
f.close()
Bs = [eval(line) for line in lines]
As described above to avoid arbitrary code execution, use the following:
Bs = [tuple([int(z, 16) for z in line[1:-1].split(',')]) for line in lines]
That way you can use for instance the first B pair, by using Bs[0], defined by the first line of B-coordinates.txt that is:
(0x1257e93a78a5b7d8fe0cf28ff1d8822350c778ac8a30e57d2acfc4d5fb8c192,0x1124ec11c77d356e042dad154e1116eda7cc69244f295166b54e3d341904a1a7)
You probably dont want to set B equal to 'data' (as a string) but instead to data (as the variable)
replace B = 'data' with B = data in the last row
Your data seems to be a tuple of hex-strings.
Use int(hex_string, 16) to convert them (since hex is base 16 not 10)
EDIT based on comment:
Assuming your file looks like this:
with open("B-coordinates.txt", "r") as file:
raw = file.read()
data = [tuple(int(hex_str, 16) for hex_str in item[1:-1].split(",")) for item in raw.split("\n")]
You can then get the first Bx, By like this:
Bx, By = data[0]

How do I import this file of data in Python?

So I just started with Python and I have no idea how to import the text file the way I want it to.
This is my code so far:
f = open("Data.txt", "r")
attributes = f.readlines()
w1 = 2 * np.random.random((1,19)) -1
def sigmoid(x):
return 1 / (1 + np.exp(-x))
outputs = sigmoid(np.dot(attributes, w1))
So the problem here is that I get the error message:
Cannot cast array data from dtype('float64') to dtype('<U32') according to the rule 'safe'.
I know that the problem is that the code does not read the text file as an array of numbers which is why I get the error.
This is one line in the text file:
1,1,22,22,22,19,18,14,49.895756,17.775994,5.27092,0.771761,0.018632,0.006864,0.003923,0.003923,0.486903,0.100025,1,0
I think what you want to do is something like the following:
import numpy as np
f = open("Data.txt", "r")
# Read the file, replace newline by "", split the string on commas
attributes = f.read().replace("\n", "").split(",")
# convert every element from string to float
attributes = np.array([float(element) for element in attributes])
# 20 random values in [-1,1)
w1 = 2 * np.random.random(20) - 1
def sigmoid(x):
return 1 / (1 + np.exp(-x))
outputs = sigmoid(np.dot(attributes, w1))
# Printing results
print(attributes)
print(w1)
print(outputs)
You're almost there :
import numpy as np
with open("Data.txt", "r") as f:
attributes = f.readlines()
attributes = [row.strip().split(",") for row in attributes]
attributes = [[float(x) for x in row] for row in attributes]
w1 = 2 * np.random.random((1,20)) -1
def sigmoid(x):
return 1 / (1 + np.exp(-x))
outputs = sigmoid(np.dot(np.array(attributes), w1.T))
You needed something like "list comprehension" to split values on each row (if there are more than one). Also, you were missing one element in w1 to match the dimension of attributes. And finally, you will have to use the transposition of w1 to make the production using np.dot (np.array(attributes)'s shape is (1,20) as well as w1's.
Also : always remember to use this "with" statement to open files (it automatically close the file after ending the statement ; otherwise, you might get into some trouble...)
Edit
If your real dataset contains more data, you should consider the use of pandas, which will be much more efficient :
import pandas as pd
df = pd.read_csv("Data.txt"), sep=",", header=None)
numpy_array = df.values

Python script for trasnforming ans sorting columns in ascending order, decimal cases

I wrote a script in Python removing tabs/blank spaces between two columns of strings (x,y coordinates) plus separating the columns by a comma and listing the maximum and minimum values of each column (2 values for each the x and y coordinates). E.g.:
100000.00 60000.00
200000.00 63000.00
300000.00 62000.00
400000.00 61000.00
500000.00 64000.00
became:
100000.00,60000.00
200000.00,63000.00
300000.00,62000.00
400000.00,61000.00
500000.00,64000.00
10000000 50000000 60000000 640000000
This is the code I used:
import string
input = open(r'C:\coordinates.txt', 'r')
output = open(r'C:\coordinates_new.txt', 'wb')
s = input.readline()
while s <> '':
s = input.readline()
liste = s.split()
x = liste[0]
y = liste[1]
output.write(str(x) + ',' + str(y))
output.write('\n')
s = input.readline()
input.close()
output.close()
I need to change the above code to also transform the coordinates from two decimal to one decimal values and each of the two new columns to be sorted in ascending order based on the values of the x coordinate (left column).
I started by writing the following but not only is it not sorting the values, it is placing the y coordinates on the left and the x on the right. In addition I don't know how to transform the decimals since the values are strings and the only function I know is using %f and that needs floats. Any suggestions to improve the code below?
import string
input = open(r'C:\coordinates.txt', 'r')
output = open(r'C:\coordinates_sorted.txt', 'wb')
s = input.readline()
while s <> '':
s = input.readline()
liste = string.split(s)
x = liste[0]
y = liste[1]
output.write(str(x) + ',' + str(y))
output.write('\n')
sorted(s, key=lambda x: x[o])
s = input.readline()
input.close()
output.close()
thanks!
First, try to format your code according to PEP8—it'll be easier to read. (I've done the cleanup in your post already).
Second, Tim is right in that you should try to learn how to write your code as (idiomatic) Python not just as if translated directly from its C equivalent.
As a starting point, I'll post your 2nd snippet here, refactored as idiomatic Python:
# there is no need to import the `string` module; `.strip()` is a built-in
# method of strings (i.e. objects of type `str`).
# read in the data as a list of pairs of raw (i.e. unparsed) coordinates in
# string form:
with open(r'C:\coordinates.txt') as in_file:
coords_raw = [line.strip().split() for line in in_file.readlines()]
# convert the raw list into a list of pairs (2-tuples) containing the parsed
# (i.e. float not string) data:
coord_pairs = [(float(x_raw), float(y_raw)) for x_raw, y_raw in coords_raw]
coord_pairs.sort() # you want to sort the entire data set, not just values on
# individual lines as in your original snippet
# build a list of all x and y values we have (this could be done in one line
# using some `zip()` hackery, but I'd like to keep it readable (for you at
# least)):
all_xs = [x for x, y in coord_pairs]
all_ys = [y for x, y in coord_pairs]
# compute min and max:
x_min, x_max = min(all_xs), max(all_xs)
y_min, y_max = min(all_ys), max(all_ys)
# NOTE: the above section performs well for small data sets; for large ones, you
# should combine the 4 lines in a single for loop so as to NOT have to read
# everything to memory and iterate over the data 6 times.
# write everything out
with open(r'C:\coordinates_sorted.txt', 'wb') as out_file:
# here, we're doing 3 things in one line:
# * iterate over all coordinate pairs and convert the pairs to the string
# form
# * join the string forms with a newline character
# * write the result of the join+iterate expression to the file
out_file.write('\n'.join('%f,%f' % (x, y) for x, y in coord_pairs))
out_file.write('\n\n')
out_file.write('%f %f %f %f' % (x_min, x_max, y_min, y_max))
with open(...) as <var_name> gives you guaranteed closing of the file handle as with try-finally; also, it's shorter than open(...) and .close() on separate lines. Also, with can be used for other purposes, but is commonly used for dealing with files. I suggest you look up how to use try-finally as well as with/context managers in Python, in addition to everything else you might have learned here.
Your code looks more like C than like Python; it is quite unidiomatic. I suggest you read the Python tutorial to find some inspiration. For example, iterating using a while loop is usually the wrong approach. The string module is deprecated for the most part, <> should be !=, you don't need to call str() on an object that's already a string...
Then, there are some errors. For example, sorted() returns a sorted version of the iterable you're passing - you need to assign that to something, or the result will be discarded. But you're calling it on a string, anyway, which won't give you the desired result. You also wrote x[o] where you clearly meant x[0].
You should be using something like this (assuming Python 2):
with open(r'C:\coordinates.txt') as infile:
values = []
for line in infile:
values.append(map(float, line.split()))
values.sort()
with open(r'C:\coordinates_sorted.txt', 'w') as outfile:
for value in values:
outfile.write("{:.1f},{:.1f}\n".format(*value))

Get x,y from 2d list and pass on

I'm trying to take a 2d list of locations that incl lat/ longs and get only the coordinates from the list (in column 3 and 4) to send to another function so that distances can be calculated... but I'm totally stumped.
What I have is...
EDITED from OP to show where I'm at...
x1 = -18.00 #These values don't change
y1 = 118.00
x2 = float(origList[3])
y2 = float(origList[4])
n = len(origList)
appList = []
for i in range (n-1):
appList.append(findDistance(x1, y1, x2, y2))
print appList
But now I get...File "F:\Storage\t_2\coord_find.py", line 27, in main,x2=math.fabs(origList[3])
TypeError: a float is required
So the problem is in the conversion to float???
Then all I have so far for the findDistance function (I only just started it and just want to test if arguments are being passed correctly)...
def findDistance(x1, y1, x2, y2):
cosX = math.fabs(y1 - y2)
a = 90 - x2
b = 90 - x1
Here's my updated code that is giving me this...
delx = math.fabs(y1 - y2)
TypeError: unsupported operand type(s) for -: 'float' and 'list'
I'm posting it up because I obviously didn't give a clear enough explanation and have made some changes since. AS you can see, I want to get the x2,y2 from cols 3,4.
Tried x2=float(origList[3]), y2=float(origList[4]) but that doesn't work either- I get "float()argument must be a string or a number".
Do I need to split the list somehow before trying to extract the values as floats??
import csv
import math
def fZone():
origList = [['200','12_7','Cons_pl','-20.10','120.10','C_10_T2'],['....'...]]
# origList has 30+ lines like this
x1 = -20.68 # Fixed point
x2 = 117.19 # Fixed point
n = len(origList) # list length
appList = [] # to hold returned
for i in range (n):
x2= origList[3] # I wanna get the '-20.10' col each iteration
y2= origList[4] # I wanna get the '120.10' col each iteration
appList.append(findDist(x1, y1, x2, y2))
print appList
def findDist(x1,y1,x2,y2):
delx = math.fabs(y1 - y2)
a = 90 - x2
b = 90 - x1 # formula is not finished
Your origList[0:] evaluates to origList. Try origList[0].
range(0,n-1) only goes up to n-2, and you have no need to specify the starting value of 0 since that's the default anyway. Use range(n).
You say the coordinates are in columns 3 and 4. It looks like you're somewhat new to indexing in a programming language, so I hope I don't offend with a gratuitous reminder that you might be looking for list elements 2 and 3, if you mean that these are the 3rd and 4th columns.
Also, the print should be outside the loop.
Apparently your list is containing pairs of strings, not of numbers.
In Python this conversion is never automatic so you will probably have to change the code to:
findDistance(x1, y1, float(origList[i][3]), float(origList[i][4]))
An error like
lat2= float(stnList[3])
TypeError: float() argument must be a string or a number
clearly says what was passed to float was neither a number nor a string.
Just add a print repr(stnList[3]) right before the offending statement and check out what was passed instead.
You can also the python debugger to find what the problem is, check for example this short video of a pdb session example

How to extract data in *.txt file and use it in Python?

I have a Python code that converts (u,v)to (s,d):
def d2r(d):
r = d * math.pi / 180.0
return (r)
def r2d(r):
d = r * 180.0 / math.pi
return (d)
def sd2uv(s,d):
r = d2r(d)
u = s * math.sin(r)
v = s * math.cos(r)
return (u,v)
def uv2sd(u,v):
s = math.sqrt((u*u)+(v*v))
r = math.atan2(u,v)
d = r2d(r)
if d < 0:
d = 360 + d
return (s,d)
The u data are stored in u.txt, each line has one number; the v data are stored in v.txt and each line has one number too. My question is how to extract data from these two files and then use them in the Python code to print (s,d)? Thanks!
I think this should do it:
with open('u.txt') as uf, open('v.txt') as vf:
for u,v in zip(uf,vf):
print uv2sd(float(u),float(v))
from itertools import izip, imap
with open('u.txt') as u_data, open('v.txt') as v_data:
for u,v in imap(float, izip(u_data, v_data)):
print uv2sd(u, v)
I can imagine two ways of doing this:
Read all of the data from each file into two separate lists. Iterate through both lists and compute each value until you reach the end of one of the lists.
Read one line from each file at a time. Compute the value you are looking for. Repeat until you have exhausted both files.
The first point has the advantage of saving the data for subsequent use (if needed) without having to open & read the files again. This may not work well at all if you have a very large data set in the file.
The second point has the advantage of saving some memory if you only need to use the data once in the program. This could be slower if you need to use the data over-and-over again.
The first way may look like this:
with open('u.txt') as u_file, open('v.txt') as v_file:
u_values = u_file.readlines()
v_values = v_file.readlines()
for u, v in zip(u_values, v_values):
print uv2sd(float(u), float(v))
# We can use u_values and v_values again if we need to now
The second way is what Akavall and gnibbler came up with.

Categories