I am a relative beginner to Python and as such I've been working on little things here and there in the office that strike me as something interesting that might be fun to try and code a solution.Recently, I was working with some cell phone data and decided to write a little script that would triangulate a cell phone location from ping strengths/XY locations from 3 different towers. As we only get one cell tower data returns in a exigence request anyway, this was pretty much a practice problem for me, which I would love to check the accuracy on anyway.As such, I was just looking for some critical feedback on any parts of this that could be written cleaner or functionally more efficient than what i have. It works fine if all the correct values are entered for all user inputs but I am not sure how to keep things moving along if an invalid value is entered. Right now, I just exit out of the script if a invalid number is entered and the user would have to start over. I would like to be able to loop(?) back through with the correct value after a prompt of some sort.Part 1User inputs (this was going to be a tool/script to be run from someones desktop in the shell)for tower signal strengths and then standardizing those inputs. I pulled all the math off another thread here.try:    s1=float (raw_input (please enter signal strength number 1 + --> +  ))    s2=float (raw_input (please enter signal strength number 2 + --> +  ))    s3=float (raw_input ( please enter signal strength number 3 + --> +  ))except (EOFError,ValueError,TypeError):    oops2 = raw_input(An unusuable value was entered for the signal strength, Press ENTER      and try again)    print oops2    exit()if s1  < 0.31 or s1 > 99:    badinput = raw_input(Signal strength #1 is invalid,\    please enter a value between 0.31 - 99. Press ENTER and try again)    print badinput    exit()if s2  < 0.31 or s2 > 99:    badinput = raw_input(Signal strength #2 is invalid, please enter a value between 0.31 -    99. Press ENTER and try again)    print badinput    exit()if s3  < 0.31 or s3 > 99:    badinput = raw_input(Signal strength #3 is invalid, please enter a value between 0.31 - 99. Press ENTER and try again)    print badinput    exit()    print _______________    print else:    def signal_strength(s1,s2,s3):        w1=float(s1)/(s1+s2+s3)        return w1    tower1_strength=signal_strength(s1,s2,s3)    print (standardized signal strength for tower #1-->) + ( ) + str(tower1_strength)    def signal_strength2(s1,s2,s3):        w2=float(s2)/(s1+s2+s3)        return w2    tower2_strength=signal_strength2(s1,s2,s3)    print (standardized signal strength for tower #2-->) + ( ) + str(tower2_strength)    def signal_strength3(s1,s2,s3):        w3=float(s3)/(s1+s2+s3)        return w3    tower3_strength=signal_strength3(s1,s2,s3)    print (standardized signal strength for tower #3-->) + ( ) + str(tower3_strength)    print _______________    print Part IIUser inputs to select which three towers to choose the XY data for, which is held in a dictionary. Right now I just have three sample values in the dictionary rather than all the cell tower xy's located in my AOI.# sample dictionary for cell carrier tower ID:X,Y Coordinates (Decimal Degrees), will      use carrier ID's as keylongitude = {1:-89.928573,2:-89.813409,3:-89.825694}latitude = {1:43.899751,2:43.913357,3:43.82814}try:    ID1 = int(raw_input (Carrier ID for tower #1 + --> +  ))    ID1x= longitude[ID1]    ID1y = latitude[ID1]    ID2 = int(raw_input (Carrier ID for tower #2 + --> +  ))    ID2x = longitude[ID2]    ID2y = latitude[ID2]    ID3 = int(raw_input (Carrier ID for tower #3 + --> +  ))    ID3x = longitude[ID3]    ID3y = latitude[ID3]except Exception,e:    oops = raw_input (An invalid Tower ID# was used,Please use the Carrier/Provider   supplied identification number. Press ENTER and try again)    print oops    exit()#Need to figure out how to loop back through the Tower ID# (and signal strength for that    matter) data entry chunk after exception, if possibleprint _______________print def user_x(tower1_strength,tower2_strength,tower3_strength,tx1,tx2,tx3):    x_location=float(tower1_strength*tx1)+(tower2_strength*tx2)+(tower3_strength*tx3)    return x_locationX_Coord=user_x(tower1_strength,tower2_strength,tower3_strength,ID1x,ID2x,ID3x)print (the X coordinate for the position is-->) + ( ) + str(X_Coord)def user_y(tower1_strength,tower2_strength,tower3_strength,ty1,ty2,ty3):    y_location=float(tower1_strength*ty1)+(tower2_strength*ty2)+(tower3_strength*ty3)    return y_locationY_Coord=user_y(tower1_strength,tower2_strength,tower3_strength,ID1y,ID2y,ID3y)print (the Y coordinate for the position is-->) + ( ) + str(Y_Coord)print _______________print ty = raw_input (thank you)print ty
Improving a triangulation test script
python;beginner;python 2.7;geospatial
Let's start with part I :Don't repeat yourselfYou can define small functions to avoid duplicating code for all signals.Also, you can use the relevant data structure to store information. For instance, the strength of the signal go by 3, let's put them in the same object (let's say a list to keep things simple).Finally, your attempt to write function for standardisation of signals was nice. However, you end up writing and computing the same things many times. You could compute the sum just once.Make things simple for the userInstead of asking for 3 inputs and then exit if something goes wrong, you can check each and every input as it is provided so that the user does not go through the hassle of providing many values only to get rejected because the first was invalid. Also, you do not need to exit if the input is not valid, you can just ask again.Taking the following comments into account, Part I becomes :def get_signal_strength_from_user(i):     Prompt the user to get a signal strength. Loops til a valid value (float in the right range) is provided and return it.    while True:        try:            s = float(raw_input(Please enter signal strength number  + str(i) +  --> ))        except (EOFError,ValueError,TypeError):            raw_input(An unusuable value was entered for the signal strength, Press ENTER and try again)            continue        if 0.31 <= s <= 99:            return s # s has a valid value        else:            raw_input(Signal strength is invalid (value should be in [0.31 - 99]. Press ENTER and try again)# Using variables :s1,s2,s3 = (get_signal_strength_from_user(1), get_signal_strength_from_user(2), get_signal_strength_from_user(3))print(Signals strength is , s1, s2, s3)sum_signal = s1+s2+s3w1,w2,w3 = s1/sum_signal, s2/sum_signal, s3/sum_signalprint(Standardized signals strength is , w1, w2, w3)# Using lists :nb_src = 3signals = [get_signal_strength_from_user(i+1) for i in range(nb_src)]print(Signals strenght is , signals)sum_signal = sum(signals)standard_signals = [s/sum_signal for s in signals]print(Standardized signals strength is , standard_signals)I've done it using lists and different variables so that you can pick whatever is easier for you.Now for part II :I don't really understand why you need to user to pick 3 towers out of 3 towers.CorrectnessAlso, I'd like to point out that your algorithm will not work if the same tower (or if 2 towers at the same location - which is roughly the same) is used more than once. Indeed, localisation on a plan with relative strenght from 2 sources only gives you the direction as the mathematical property you are using is right for any point of a line.My feeling is that even more than that, the towers should not be aligned because this could lead to (at least) 2 distinct points in most cases.The fact that this does not seem obvious from the code lead me to think that maybe the maths behind are wrong too.Anyway, let's go back to the code.Don't repeat yourselfIt might not seem obvious because the names of the parameters are changed but you have defined the same function twice.def user_c(tower1_strength,tower2_strength,tower3_strength,c1,c2,c3):    c = float(tower1_strength*c1) + (tower2_strength*c2) + (tower3_strength*c3)    return c(c stands for coordinate here).Also, the conversion and the temporary variable are not useful here, the argument names do not need to be that long and the function could be renamed :def mean(s1,s2,s3,c1,c2,c3):    return s1*c1 + s2*c2 + s3*c3