Trying to summarize list in arcpy - cursor

I have a list of xy points that I'm trying to sum together and identify the centroid, but it only uses the last value in the row. I'm trying to create a centroid for each state, Here's the code:
Total_X1 = 0
Total_Y1 = 0
TotalPop1 = 0
#Cat = "cali"
cntyName1 = "cnty"
stateName1 = "statename"
for row in cursor:
#if row[0] >= : ### for condition that is met
#if row[0]== []:
TheStateName1 = row[0]
thecntyName1 = row[4]
idpoly1 = row[5]
idobject1 = row[6]
stateFIPS1 = row[7]
countyFIPS1 = row[8]
fips1 = row[9]
fipSnum1 = row[10]
fipsNumer1 = row[11]
#totarea = row[12]
XPoint = row [13]
YPoint = row[14]
#print Cat
print TheStateName1
print thecntyName1
print row ### do something with that value!
Total_X1 += row[2] *row[3]
print Total_X1
Total_Y1 += row[1] *row[3]
print Total_Y1
TotalPop1 += row[3]
print TotalPop1
print ""
print "X is: " , Total_X1
print "POP is: " , TotalPop1
centroid_X1 = Total_X1/TotalPop1
print "your x centroid is: ",centroid_X1
print ""
#print Cat
print thecntyName1
print TheStateName1
Any Suggestions, Thanks!

The cursor can only 'see' one row at a time, you have to pull info from that row and store it elsewhere.
loc_list = [(row[0], row[1]) for row in arcpy.da.SearchCursor(dataset, ['X_coord', 'Y_coord'])
Will give you a list of X,Y tuples from your attribute table.
After that you've got multiple options for turning that list of tuples into a spatial dataset before calculating the mean - start by reading the ESRI documentation for arcpy.Point and all the related topics linked, and go from there. If you have 10.3 or above you can use Mean Center once you have a point layer.
You'll probably get a wrong answer if you just take the mean of the X and Y without projecting first, so don't.

Related

how do I insert values while using Hash.Lib while using while loop?

I have the following code... How would I be able to insert values in the array list with different indexes while its looping inside of a while loop? from the 2nd function(HashMine(CarID1))
local function HistoryHash() -- This function is to print out the Hashes "Mined" using Hash.Lib
for Hashindex = 1, #HashHistory do
print("Hash "..Hashindex..":", HashHistory[Hashindex])
end
end
--Mines the BTC pending transaction
local function HashMine(CarID1)
while stringtohash:sub(1,2) ~= "00" do
STRINGTOHASH = stringtohash..HASHNUMBER
stringtohash = HASHLIBRARY.sha256(STRINGTOHASH)
HASHNUMBER = HASHNUMBER + 1
wait(1)
table.insert()
end
HashGUI.Text = stringtohash
PendingTextGui.Text = ""
local CarID1 = CarBought
if CarID1 == 1 then
ConfirmedText.Text = ("Car1 ".. game.Workspace.Cars.Car1Buy.Car1.Value .. "BTC To Malta Car Dealer from " .. Players:GetChildren()[1].Name)
AfterCarPurchase()
elseif CarID1 == 2 then
ConfirmedText.Text = ("Car2 ".. game.Workspace.Cars.Car2Buy.Car2.Value.. "BTC To Malta Car Dealer from " .. Players:GetChildren()[1].Name)
AfterCarPurchase()
elseif CarID1 == 3 then
ConfirmedText.Text = ("Car3 ".. game.Workspace.Cars.Car3Buy.Car3.Value .. "BTC To Malta Car Dealer from " .. Players:GetChildren()[1].Name)
end
AfterCarPurchase()
end
table.insert() will cause the error message
bad argument #1 to 'insert' (table expected, got no value)
According to the Lua 5.4 Reference Manual - table.insert, it is mandatory to provide the table you want to insert to and the value you want to to insert into that table.
table.insert (list, [pos,] value)
Inserts element value at position pos in list, shifting up the
elements list[pos], list[pos+1], ยทยทยท, list[#list]. The default value
for pos is #list+1, so that a call table.insert(t,x) inserts x at the
end of the list t.
If you want to assign a value to a specific table index you need to use indexing assignmet t[key] = value

Repeat current poly reduce function on multiple objects that are selected?

I'm looping through multiple objects, but the loop stops before going to the next object.
Created a loop with condition. If condition is met, it calls a ReduceEdge() function. Problem is it will only iterate once and not go to the next object and repeat the procedure.
global proc ReduceEdge()
{
polySelectEdgesEveryN "edgeRing" 2;
polySelectEdgesEveryN "edgeLoop" 1;
polyDelEdge -cv on;
}
string $newSel[] = `ls -sl`;
for($i = 0; $i < size($newSel); $i++)
{
select $newSel[$i];
int $polyEval[] = `polyEvaluate -e $newSel[$i]`;
int $temp = $polyEval[0];
for($k = 0; $k < $temp; $k++)
{
string $polyInfo[] = `polyInfo -fn ($newSel[$i] + ".f[" + $k + "]")`;
$polyInfo = stringToStringArray($polyInfo[$i]," ");
float $vPosX = $polyInfo[2];
float $vPosY = $polyInfo[3];
float $vPosZ = $polyInfo[4];
if($vPosX == 0 && $vPosY == 0 && $vPosZ == 1.0)
{
select ($newSel[$i] + ".e[" + $k + "]");
ReduceEdge();
}
}
}
Expected results:
If I select 4 cylinders, all their edges will reduce by half the current amount.
Actual results:
When 4 cylinders are selected, only one reduces down to half the edges. The rest stay the same.
Since my comment did help you out, I'll try and give a more thorough explanation.
Your first loop (with $i) iterates over each object in your selection. This is fine.
Your second loop (with $k) iterates over the number of edges for the current object in the loop. So far, so good. Though, I'm wondering if it would be more correct to loop of the number of faces...
Now you ask for an array of all face normals of the face at index $k at object $i, with string $polyInfo[] = `polyInfo -fn ($newSel[$i] + ".f[" + $k + "]")`;.
If you try and print the size and values in $polyInfo, you'll realize you have an array with one element, which is the face normal of the particular face you queried just before. Therefore, it will always be element 0, and not $i, which would increases with every iteration.
I have made a Python/PyMEL version of the script, which may be nice for you to see.
import pymel.core as pm
import maya.mel as mel
def reduceEdge():
mel.eval('polySelectEdgesEveryN "edgeRing" 2;')
mel.eval('polySelectEdgesEveryN "edgeLoop" 1;')
pm.polyDelEdge(cv=True)
def reducePoly():
selection = pm.ls(sl=True)
for obj in selection:
for i, face in enumerate(obj.f):
normal = face.getNormal()
if (normal.x == 0.0 and normal.y == 0.0 and normal.z == 1.0):
pm.select(obj + '.e[' + str(i) + ']')
reduceEdge()
reducePoly()

LUA getting values from table by using a string

How would I go about compiling values from a table using a string?
i.e.
NumberDef = {
[1] = 1,
[2] = 2,
[3] = 3
}
TextDef = {
["a"] = 1,
["b"] = 2,
["c"] = 3
}
If I was for example to request "1ABC3", how would I get it to output 1 1 2 3 3?
Greatly appreciate any response.
Try this:
s="1ABC3z9"
t=s:gsub(".",function (x)
local y=tonumber(x)
if y~=nil then
y=NumberDef[y]
else
y=TextDef[x:lower()]
end
return (y or x).." "
end)
print(t)
This may be simplified if you combine the two tables into one.
You can access values in a lua array like so:
TableName["IndexNameOrNumber"]
Using your example:
NumberDef = {
[1] = 1,
[2] = 2,
[3] = 3
}
TextDef = {
["a"] = 1,
["b"] = 2,
["c"] = 3
}
print(NumberDef[2])--Will print 2
print(TextDef["c"])--will print 3
If you wish to access all values of a Lua array you can loop through all values like so (similarly to a foreach in c#):
for i,v in next, TextDef do
print(i, v)
end
--Output:
--c 3
--a 1
--b 2
So to answer your request, you would request those values like so:
print(NumberDef[1], TextDef["a"], TextDef["b"], TextDef["c"], NumberDef[3])--Will print 1 1 2 3 3
One more point, if you're interested in concatenating lua string this can be accomplished like so:
string1 = string2 .. string3
Example:
local StringValue1 = "I"
local StringValue2 = "Love"
local StringValue3 = StringValue1 .. " " .. StringValue2 .. " Memes!"
print(StringValue3) -- Will print "I Love Memes!"
UPDATE
I whipped up a quick example code you could use to handle what you're looking for. This will go through the inputted string and check each of the two tables if the value you requested exists. If it does it will add it onto a string value and print at the end the final product.
local StringInput = "1abc3" -- Your request to find
local CombineString = "" --To combine the request
NumberDef = {
[1] = 1,
[2] = 2,
[3] = 3
}
TextDef = {
["a"] = 1,
["b"] = 2,
["c"] = 3
}
for i=1, #StringInput do --Foreach character in the string inputted do this
local CurrentCharacter = StringInput:sub(i,i); --get the current character from the loop position
local Num = tonumber(CurrentCharacter)--If possible convert to number
if TextDef[CurrentCharacter] then--if it exists in text def array then combine it
CombineString = CombineString .. TextDef[CurrentCharacter]
end
if NumberDef[Num] then --if it exists in number def array then combine it
CombineString = CombineString .. NumberDef[Num]
end
end
print("Combined: ", CombineString) --print the final product.

Arranging the fields of a structure into order

I am trying find away of ordering a polynomial in the form a structure so that the exponent fields are in ascending order. I don't want to use a built in sort function to do this.
for example the polynomial:
p = struct('exponent',{2,3,2,9},'coeff',{1,2,91,40})
represents the polynomial:
p = 1(x^2) + 2(x^3) + 91(x^2)+ 40(x^9)
I want to rearrange it so that it becomes (the exponents are now in ascending order)
p = 1(x^2) + 91(x^2) + 2(x^3) + 40(x^9)
my code to do this is:
function [ output ] = myMergepoly2( p )
h=1;
output(1,length(p))=struct('exponent',{},'coeff',{});
while (h<length(p))
if p(1,h+1).exponent<p(1,h).exponent
output(1,h).exponent = p(1,h+1).exponent;
output(1,h).coeff = p(1,h+1).coeff;
h=h+1;
else
output(1,h).exponent = p(1,h).exponent;
output(1,h).coeff = p(1,h).coeff;
end
end
end
However when I try to run this function MATLAB remote has 'busy' written out with no error message. I am unsure what is causing this and how to fix it, any help would be appreciated.
In the else section of the loop, you don't increment h, so it goes like this:
h=1 --> if p(1,h+1).exponent<p(1,h).exponent is false --> skip to else loop and set output(1,1).exponent --> h=1 (while loop keeps going).
Using MATLAB inbuilt sort I'd just do something along the lines of:
exponent = [p.exponent];
coeff = [p.coeff];
[exponent idx] = sort(exponent);
output.exponent = exponent;
output.coeff = coeff(idx);
Replace this line :
output(1,length(p))=struct('exponent',{},'coeff',{});
With this line :
output = struct('exponent',cell(1,length(p)),'coeff',cell(1,length(p)));
Also put this instead:
while (h<length(p))
if p(1,h+1).exponent<p(1,h).exponent
output(1,h).exponent = p(1,h+1).exponent;
output(1,h).coeff = p(1,h+1).coeff;
else
output(1,h).exponent = p(1,h).exponent;
output(1,h).coeff = p(1,h).coeff;
end
h=h+1;
end
However I'm still not getting the right output, I'm working on it.

Getting current position of one of the multiple objects in a figure?

I wrote a script that returns several text boxes in a figure. The text boxes are moveable (I can drag and drop them), and their positions are predetermined by the data in an input matrix (the data from the input matrix is applied to the respective positions of the boxes by nested for loop). I want to create a matrix which is initially a copy of the input matrix, but is UPDATED as I change the positions of the boxes by dragging them around. How would I update their positions? Here's the entire script
function drag_drop=drag_drop(tsinput,infoinput)
[x,~]=size(tsinput);
dragging = [];
orPos = [];
fig = figure('Name','Docker Tool','WindowButtonUpFcn',#dropObject,...
'units','centimeters','WindowButtonMotionFcn',#moveObject,...
'OuterPosition',[0 0 25 30]);
% Setting variables to zero for the loop
plat_qty=0;
time_qty=0;
k=0;
a=0;
% Start loop
z=1:2
for idx=1:x
if tsinput(idx,4)==1
color='red';
else
color='blue';
end
a=tsinput(idx,z);
b=a/100;
c=floor(b); % hours
d=c*100;
e=a-d; % minutes
time=c*60+e; % time quantity to be used in 'position'
time_qty=time/15;
plat_qty=tsinput(idx,3)*2;
box=annotation('textbox','units','centimeters','position',...
[time_qty plat_qty 1.5 1.5],'String',infoinput(idx,z),...
'ButtonDownFcn',#dragObject,'BackgroundColor',color);
% need to new=get(box,'Position'), fill out matrix OUT of loop
end
fillmenu=uicontextmenu;
hcb1 = 'set(gco, ''BackgroundColor'', ''red'')';
hcb2 = 'set(gco, ''BackgroundColor'', ''blue'')';
item1 = uimenu(fillmenu, 'Label', 'Train Full', 'Callback', hcb1);
item2 = uimenu(fillmenu, 'Label', 'Train Empty', 'Callback', hcb2);
hbox=findall(fig,'Type','hggroup');
for jdx=1:x
set(hbox(jdx),'uicontextmenu',fillmenu);
end
end
new_arr=tsinput;
function dragObject(hObject,eventdata)
dragging = hObject;
orPos = get(gcf,'CurrentPoint');
end
function dropObject(hObject,eventdata,box)
if ~isempty(dragging)
newPos = get(gcf,'CurrentPoint');
posDiff = newPos - orPos;
set(dragging,'Position',get(dragging,'Position') + ...
[posDiff(1:2) 0 0]);
dragging = [];
end
end
function moveObject(hObject,eventdata)
if ~isempty(dragging)
newPos = get(gcf,'CurrentPoint');
posDiff = newPos - orPos;
orPos = newPos;
set(dragging,'Position',get(dragging,'Position') + [posDiff(1:2) 0 0]);
end
end
end
% Testing purpose input matrices:
% tsinput=[0345 0405 1 1 ; 0230 0300 2 0; 0540 0635 3 1; 0745 0800 4 1]
% infoinput={'AJ35 NOT' 'KL21 MAN' 'XPRES'; 'ZW31 MAN' 'KM37 NEW' 'VISTA';
% 'BC38 BIR' 'QU54 LON' 'XPRES'; 'XZ89 LEC' 'DE34 MSF' 'DERP'}
If I understand you correctly (and please post some code if I'm not), then all you need is indeed a set/get combination.
If boxHandle is a handle to the text-box object, then you get its current position by:
pos = get (boxHandle, 'position')
where pos is the output array of [x, y, width, height].
In order to set to a new position, you use:
set (boxHandle, 'position', newPos)
where newPos is the array of desired position (with the same structure as pos).
EDIT
Regarding to updating your matrix, since you have the handle of the object you move, you actually DO have access to the specific text box.
When you create each text box, set a property called 'UserData' with the associated indices of tsinput used for that box. In your nested for loop add this
set (box, 'UserData', [idx, z]);
after the box is created, and in your moveObject callback get the data by
udata = get(dragging,'UserData');
Then udata contains the indices of the elements you want to update.

Resources