I am working on Ironpython in Revit application.
This is the code below I was trying in python. Help would be appreciated.
From the list of points, there is a first point and second point. I have created functions for them.
The script should check if the y coordinates are same and draw line if true.
Its not working and returning unexpected error - new line error.
`The inputs to this node will be stored as a list in the IN variables.`
points = IN[0]
`# Place your code below this line`
lines = []
def fp(x)
firstpoint = points[x]
return firstpoint
def sp(x)
secondpoint = points[x+1]
return secondpoint
x = 0
while x <= points.Count:
if (fp(x).Y == sp(x).Y) or (fp(x).Z == sp(x).Z):
setlines = Line.ByStartPointEndPoint(fp(x), sp(x))
lines.append(setlines)
x = x + 1
`# Assign your output to the OUT variable.`
OUT = lines
As #itprorh66 points out, there's really not enough info here to definitively answer your question, but one issue is you're incorrectly comparing what I assume are floats.
fp(x).Y == sp(x).Y
Instead of comparing for direct equality, you'll need to compare for equality within a tolerance. Here is some discussion on how to do that, What is the best way to compare floats for almost-equality in Python?
I have a code that I inform a folder, where it has n images that the code should return me the relative frequency histogram.
From there I have a function call:
for image in total_images:
histogram(image)
Where image is the current image that the code is working on and total_images is the total of images (n) it has in the previously informed folder.
And from there I call the histogram() function, sending as a parameter the current image that the code is working.
My histogram() function has the purpose of returning the histogram of the relative frequency of each image (rel_freq).
Although the returned values are correct, rel_freq should be a array 1x256 positions ranging from 0 to 255.
How can I transform the rel_freq variable into a 1x256 array? And each value stored in its corresponding position?
When I do len *rel_freq) it returns me 256, that's when I realized that it is not in the format I need...
Again, although the returned data is correct...
After that, I need to create an array store_all = len(total_images)x256 to save all rel_freq...
I need to save all rel_freq in an array to later save it and to an external file, such as .txt.
I'm thinking of creating another function to do this...
Something like that, but I do not know how to do it correctly, but I believe you will understand the logic...
def store_all_histograms(total_images):
n = len(total_images)
store_all = [n][256]
for i in range(0,n):
store_all[i] = rel_freq
I know the function store_all_histograms() is wrong, I just wrote it here to show more or less the way I'm thinking of doing... but again, I do not know how to do it properly... At this point, the error I get is:
store_all = [n][256]
IndexError: list index out of range
After all, I need the store_all variable to save all relative frequency histograms for example like this:
position: 0 ... 256
store_all = [
[..., ..., ...],
[..., ..., ...],
.
.
.
n
]
Now follow this block of code:
def histogram(path):
global rel_freq
#Part of the code that is not relevant to the question...
rel_freq = [(float(item) / total_size) * 100 if item else 0 for item in abs_freq]
def store_all_histograms(total_images):
n = len(total_images)
store_all = [n][256]
for i in range(0,n):
store_all[i] = rel_freq
#Part of the code that is not relevant to the question...
# Call the functions
for fn in total_images:
histogram(fn)
store_all_histograms(total_images)
I hope I have managed to be clear with the question.
Thanks in advance, if you need any additional information, you can ask me...
Return the result, don't use a global variable:
def histogram(path):
return [(float(item) / total_size) * 100 if item else 0 for item in abs_freq]
Create an empty list:
store_all = []
and append your results:
for fn in total_images:
store_all.append(histogram(fn))
Alternatively, use a list comprehension:
store_all = [histogram(fn) for fn in total_images]
for i in range(0,n):
store_all[i+1] = rel_freq
Try this perhaps? I'm a bit confused on the question though if I'm honest. Are you trying to shift the way you call the array with all the items by 1 so that instead of calling position 1 by list[0] you call it via list[1]?
So you want it to act like this?
>>list = [0,1,2,3,4]
>>list[1]
0
I'm getting really confused with all the information on here using 'split' in python. Basically I want to write a code which opens a spreadsheet (with two columns in it) and the function I write will use the first column as x's and the second column as y's and then it will plot it in the x-y plane.
I thought I would use line.splitlines to cut each line in excel into (x,y) but I keep getting
'ValueError: need more than 1 value to unpack'
I don't know what this means?
Below is what I've written so far, (xdir is an initial condition for a different part of my question):
def plotMo(filename, xdir):
infile = open(filename)
data = []
for line in infile:
x,y = line.splitlines()
x = float(x)
y = float(y)
data.append([x,y])
infile.close()
return data
plt.plot(x,y)
For example with
0 0.049976
0.01 0.049902
0.02 0.04978
0.03 0.049609
0.04 0.04939
0.05 0.049123
0.06 0.048807
I would want to the first point in my plane to be (0, 0.049976) and the second plot to be (0.01, 0.049902).
x,y = line.splitlines() tries to split the current line into several lines.
Since splitlines returns only 1 element, there's an error because python cannot find a value to assign to y.
What you want is x,y = line.split() which will split the line according to 1 or more spaces (like awk would do) if no parameter is specified.
However it depends of the format: if there are blank lines you'll get the "unpack" problem at some point, so to be safe and skip malformed lines, write:
items = line.split()
if len(items)==2: x,y = items
To sum it up, a more pythonic, shorter & safer way of writing your routine would be:
def plotMo(filename):
with open(filename) as infile:
data = []
for line in infile:
items = line.split()
if len(items)==2:
data.append([float(e) for e in items])
return data
(maybe it could be condensed more, but that's good for starters)
I have a file that is space delimited with values for x,y,x. I need to visualise the data so I guess I need so read the file into 3 separate arrays (X,Y,Z) and then plot them. How do I read the file into 3 seperate arrays I have this so far which removes the white space element at the end of every line.
def fread(f=None):
"""Reads in test and training CSVs."""
X = []
Y = []
Z = []
if (f==None):
print("No file given to read, exiting...")
sys.exit(1)
read = csv.reader(open(f,'r'),delimiter = ' ')
for line in read:
line = line[:-1]
I tried to add something like:
for x,y,z in line:
X.append(x)
Y.append(y)
Z.append(z)
But I get an error like "ValueError: too many values to unpack"
I have done lots of googling but nothing seems to address having to read in a file into a separate array every element.
I should add my data isn't sorted nicely into rows/columns it just looks like this
"107745590026 2 0.02934046648 0.01023879368 3.331810236 2 0.02727724425 0.07867902517 3.319272757 2 0.01784882881"......
Thanks!
EDIT: If your data isn't actually separated into 3-element lines (and is instead one long space-separated list of values), you could use python list slicing with stride to make this easier:
X = read[::3]
Y = read[1::3]
Z = read[2::3]
This error might be happening because some of the lines in read contain more than three space-separated values. It's unclear from your question exactly what you'd want to do in these cases. If you're using python 3, you could put the first element of a line into X, the second into Y, and all the rest of that line into Z with the following:
for x, y, *z in line:
X.append(x)
Y.append(y)
for elem in z:
Z.append(elem)
If you're not using python 3, you can perform the same basic logic in a slightly more verbose way:
for i, elem in line:
if i == 0:
X.append(elem)
elif i == 1:
Y.append(elem)
else:
Z.append(elem)
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I'm pretty new to Python and I'm trying to write a program that will do a 4-point linear interpolation reading data from a .txt file and asking for user information.
The .txt file has temperature and pressures in a table with this format:
T P1 P2 P3 P4
80,100,150,200
75, 400,405,415,430
100, 450,456,467,483
150, 500,507,519,536
200, 550,558,571,589
And here's the code:
# User input
temp = input("Enter temperature value in degrees Celcius [Range: 75-200]:")
pressure = input("Enter pressure value in bars [Range: 80-589")
temp = float(temp)
pressure = float(pressure)
# Opens file and read data
filename = open('xxxxxxxxxxxxx.txt', 'r').readlines()
# Removes \n from each line
for i in list(range((len(filename)-1))):
filename[i] = filename[i][:-1]
# Splits string
for i in list(range(len(filename))):
filename[i] = filename[i].split(',')
# Converts string numbers into decimal numbers
for i in [2,3,4,5,6]:
filename[i][0] = float(filename[i][0])
filename[i][1] = float(filename[i][1])
I'm not sure where to go from here. If the user input was say, T=100 and P=200, how would I locate the data points from the file that are directly before and after those numbers?
Obviously, I don't know much about what I'm doing, but I would appreciate any help.
ETA: Actual table values.
Also, I was not clear on the actual problem statement. Given a temperature and pressure, the program should perform an linear interpolation to find U (internal energy). The T values are the first column, the P values the first row, and the rest are U values.
There are two separate questions here: how to read data into python / NumPy,
and how to do 2d interpolatation.
For reading data, I'd suggest
numpy loadtxt,
and for interpolation,
scipy BivariateSpline.
(They both have more options than you need.)
from __future__ import division
from cStringIO import StringIO
import numpy as np
from scipy.interpolate import RectBivariateSpline
np.set_printoptions( 1, threshold=100, edgeitems=10, suppress=True )
# a file inline, for testing --
myfile = StringIO( """
# T P1 P2 P3 P4
0, 80,100,150,200
75, 400,405,415,430
100, 450,456,467,483
150, 500,507,519,536
200, 550,558,571,589
""" )
# file -> numpy array --
# (all rows must have the same number of columns)
TPU = np.loadtxt( myfile, delimiter="," )
P = TPU[0,1:] # top row
T = TPU[ 1:,0] # left col
U = TPU[1:,1:] # 4 x 4, 400 .. 589
print "T:", T
print "P:", P
print "U:", U
interpolator = RectBivariateSpline( T, P, U, kx=1, ky=1 ) # 1 bilinear, 3 spline
# try some t, p --
for t, p in (
(75, 80),
(75, 200),
(87.5, 90),
(200, 80),
(200, 90),
):
u = interpolator( t, p )
print "t %5.1f p %5.1f -> u %5.1f" % (t, p, u)
By the way, for interactive python,
IPython
makes it easy to try single lines, look at variables ...
Assuming you have a sorted list of numbers, x1, x2, x3... xn, you could use the bisect module for fast location of the interval you want (O(log n)).
from bisect import bisect, bisect_right, bisect_left
# 0 1 2 3 4 5 6 7
x = [1, 2, 4, 8, 16, 100, 200, 300]
def find_interval(x,y):
# x must be a sorted list.
index = bisect_left(x,y)
# Larger than largest element in x
if index >= len(x):
l,r = -1, None
# Exactly equal to something in x
elif y == x[index]:
l,r = index, index
# Smaller than smallest element in x
elif index == 0:
l,r = None, 0
# Inbetween two elements in x
else:
l,r = index-1, index
print (x[l] if l != None else "To left of all elements")
print (x[r] if r != None else "To right of all elements")
return (l,r)
>>> x
[1, 2, 4, 8, 16, 100, 200, 300]
>>> find_interval(x,0)
To left of all elements
1
>>> find_interval(x,1000)
300
To right of all elements
>>> find_interval(x,100)
100
100
>>> find_interval(x,12)
8
16
>>>
Using .readlines() will shoot you in the foot as soon as the file gets big. Can you formulate what you need to do in terms of
for line in open(...):
# parse line
and parse the file just once without loading it fully into memory.
Much better still, would be to use the with idiom when working with files:
with open(...) as file:
for line in file:
# parse line
This saves you a bit of headaches when there is a problem while working with the file.
You don't need to strip newlines if you will end up using float() to make a float out of a string. float('1.2 \t\n') is perfectly valid code.
for i in list(range(len(filename))):
This is bad style. The Python idiom for iterating through a list is
for element in list:
If you need an index into the list, then you should use
for i, element in enumerate(list):
Your approach is sort-of "manual" and it works, but creating a list out of a list (coming from range(...) in python 2.x) is completely unnecessary. A better "manual" alternative to your code would be
for i in xrange(len(filename)):
but it is still much less readable than the idioms above.
Now that I'm done bashing on your code, the main question is: what [the hell] do you actually need done? Can you give us the exact, word-for-word, specification of the problem you are trying to solve?
Have you looked at http://en.wikipedia.org/wiki/Linear_interpolation?
What is the significance of the input data from the terminal in your case?
Why and what for do you need the data from the file that is just before and after the input data from the terminal?
Is the temperature/pressure data somehow sorted?
What do the lines in the file represent (e.g. are they time-based or location-based or something else)?
What do the four different pressures represent?