am working on developing a python toolbox to automate the steps required for checking data out and back into a file geodatabase. My question is what is the best way to limit the features checked out to only those selected while using the python command line and ArcPad Data Management tools instead of the ArcPad data manager? The "Only get selected features" checkbox in the ArcPad Data Manager makes it easy. This is important because I want to limit the areas of use and reduce the file size as one of the feature classes is a large parcel map.
I do know one way to get selected items by using arcpy only.
#get an map object
mxd = arcpy.mapping.MapDocument("CURRENT")
#get an dataframe object, here the first one is taken
df = arcpy.mapping.ListDataFrames(mxd)[0]
#get a layer object
lyr = arcpy.mapping.ListLayers(mxd,"NameOfRequiredLayer",df)
#now get the FIDs of the selected Elements of your layer
selection = arcpy.Describe(lyr).FIDSet
"selection" then contains the FIDs of selected elements. With that you can carry one with whatever you have to do. For instance you can then set a layers definition query:
#shapes use FID, feature classes use OBJECTID, so you better check
IDname = "\"OBJECTID\""
if lyr.dataSource.endswith("shp"):
IDname = "\"FID\""
querystring = IDname + " = " + str(selection[0])
for count in range(1,len(selection)):
querystring = querystring + " OR " + IDname + " = " + str(selection[count])
if lyr.supports("DEFINITIONQUERY"):
lyr.definitionQuery = querystring
Related
I am trying to display elements from an XML file in tkinter Entry and Text widgets.
Example XML:
<notes>
<note id="5/10/22/14:20">
<index>5/10/22, 14:20 > Mr Anderson</index>
<date>5/10/22</date>
<time>14:20</time>
<from>Agt Smith</from>
<to>Mr Anderson</to>
<subject>App Test 3</subject>
<body>Do you hear that, Mr. Anderson? That is the sound of inevitability.</body>
</note>
</notes>
I was going to try getchildren() but I am told that is deprecated. I want to use the note id to pull up that element and its children, and insert various children into the correlating Entry and Text widgets. However, I cannot seem to get the correct values into variables. It feels like it should be simple and easy, but my instincts are leading me astray. What I am getting from this code is all of the entries displaying, rather than one selected by the note id. This is my code:
def displayNote(self):
# Clear the boxes first
clearBoxes()
# get index value
for i in noteList.curselection():
noteIndex = noteList.get(i)
# process index value to get id
subStrip = ' >.*'
noteStrip = noteIndex.replace(", " , "/").replace(":" , "")
noteID = re.sub(subStrip , "" , noteStrip)
# parse xml for box display
fileForDisplay = ET.parse(notefile)
rootd = fileForDisplay.getroot()
# and pull the info for that note id into variables
for note in rootd.findall('note'):
dateInfo = note.find("date").text
toInfo = note.find("to").text
fromInfo = note.find("from").text
subjectInfo = note.find("subject").text
bodyInfo = note.find("body").text
timeInfo = note.find("time").text
bodyDisplay = timeInfo + "\n" + bodyInfo
I'm new in programming and I need to write a code that create an odb that visualize max value of six field output of a single step. For every single node I would like represent the max value of each field output.
Now I've created a code which results in this this error:
myFieldOutput.addData(position=INTEGRATION_POINT, instance=instance1, data=maxStress)
omu_PrimArray from sequence failed - dimensions.
This is the code:
from abaqus import *
from abaqusConstants import *
import visualization
myViewport = session.Viewport(name='Max_Stess',
origin=(10, 10), width=150, height=100)
# Open the tutorial output database.
myOdb = visualization.openOdb(path='PROVA_04_10.odb', readOnly=False)
# Associate the output database with the viewport.
myViewport.setValues(displayedObject=myOdb)
instance1 = myOdb.rootAssembly.instances['MODIFICA_FUNZIONANTE']
# Create variables that refer to the first steps.
firstStep = myOdb.steps['sigma_equivalenti']
frame = firstStep.frames[-1]
#creo nuovo step
# lettura degli stress dallo step sigma
sigma_eq_1 = frame.fieldOutputs['sigma_eq_1']
sigma_eq_2 = frame.fieldOutputs['sigma_eq_2']
sigma_eq_3 = frame.fieldOutputs['sigma_eq_3']
sigma_eq_4 = frame.fieldOutputs['sigma_eq_4']
sigma_eq_5 = frame.fieldOutputs['sigma_eq_5']
sigma_eq_6 = frame.fieldOutputs['sigma_eq_6']
#calcolo del vettore degli sforzi massimi
maxStress=[]
for i in range(len(sigma_eq_1.values)):
v1=sigma_eq_1.values[i]
v2=sigma_eq_2.values[i]
v3=sigma_eq_3.values[i]
v4=sigma_eq_4.values[i]
v5=sigma_eq_5.values[i]
v6=sigma_eq_6.values[i]
maxStress.append((max(v1,v2,v3,v4,v5,v6),)) #max(valori)
myFieldOutput = frame.FieldOutput(name='tensioni_max',description='calcolo delle tensioni massime', type=SCALAR)
myFieldOutput.addData(position=INTEGRATION_POINT, instance=instance1, data=maxStress)
#visualizzazione della variabile delle sigma massima sul programma
myViewport.odbDisplay.setPrimaryVariable(field=myFieldOutput,outputPosition=INTEGRATION_POINT)
myViewport.odbDisplay.display.setValues(plotState=(CONTOURS_ON_DEF,))
You could use field argument to add the field output data as FieldOutput object. However, you should create the field data from already existing field outputs.
In your case, you could do the following:
Access the field output (NOT the field output data), as you did correctly.
sigma_eq_1 = frame.fieldOutputs['sigma_eq_1']
sigma_eq_2 = frame.fieldOutputs['sigma_eq_2']
sigma_eq_3 = frame.fieldOutputs['sigma_eq_3']
sigma_eq_4 = frame.fieldOutputs['sigma_eq_4']
sigma_eq_5 = frame.fieldOutputs['sigma_eq_5']
sigma_eq_6 = frame.fieldOutputs['sigma_eq_6']
Then, manipulate these field output data. You can do any feasible mathematical operation on these data, for ex. add, substract,etc. In this case, to find maximum value, we have specific command called maxEnvelope.
maxS = maxEnvelope([sigma_eq_1, sigma_eq_2, sigma_eq_3, sigma_eq_4, sigma_eq_5, sigma_eq_6])
Please note, this command takes list as an argument. And this command calculates the new field data at the same position where the original data is availble. In this case, it is available at Integration Point, hence it will be written at Integration Point.
3. Now, you could use field arugment to add field output data.
myFieldOutput = frame.FieldOutput(name='tensioni_max',description='calcolo delle tensioni massime', type=SCALAR)
myFieldOutput.addData(field=maxS[0])
P.S.: As you have imported visualization module as import visualization, you should use maxEnvelope method as visualization.maxEnvelope(...)
Lets say I have an assembly like this:
MainProduct:
-Product1 (Instance of Part1)
-Product2 (Instance of Part2)
-Product3 (Instance of Part2)
-Product4 (Instance of Part3)
...
Now, I want to copy/paste a feature from Product3 into another one.
But I run into problems when selecting the feature programmatically, because there are 2 instances of the part of that feature.
I can't control which feature will be selected by CATIA.ActiveDocument.Selection.Add(myExtractReference)
Catia always selects the feature from Product2 instead of the feature from Product3. So the position of the pasted feature will be wrong!
Does anybody know this problem and has a solution to it?
Edit:
The feature reference which I want to copy already exists as a variable because it was newly created (an extract of selected geometry)
I could get help else where. Still want to share my solution. It's written in Python but in VBA its almost the same.
The clue is to access CATIA.Selection.Item(1).LeafProduct in order to know where the initial selection was made.
import win32com.client
import pycatia
CATIA = win32com.client.dynamic.DumbDispatch('CATIA.Application')
c_doc = CATIA.ActiveDocument
c_sel = c_doc.Selection
c_prod = c_doc.Product
# New part where the feature should be pasted
new_prod = c_prod.Products.AddNewComponent("Part", "")
new_part_doc = new_prod.ReferenceProduct.Parent
# from user selection
sel_obj = c_sel.Item(1).Value
sel_prod_by_user = c_sel.Item(1).LeafProduct # reference to the actual product where the selection was made
doc_from_sel = sel_prod_by_user.ReferenceProduct.Parent # part doc from selection
hb = doc_from_sel.Part.HybridBodies.Add() # new hybrid body for the extract. will be deleted later on
extract = doc_from_sel.Part.HybridShapeFactory.AddNewExtract(sel_obj)
hb.AppendHybridShape(extract)
doc_from_sel.Part.Update()
# Add the extract to the selection and copy it
c_sel.Clear()
c_sel.Add(extract)
sel_prod_by_catia = c_sel.Item(1).LeafProduct # reference to the product where Catia makes the selection
c_sel_copy() # will call Selection.Copy from VBA. Buggy in Python.
# Paste the extract into the new part in a new hybrid body
c_sel.Clear()
new_hb = new_part_doc.Part.HybridBodies.Item(1)
c_sel.Add(new_hb)
c_sel.PasteSpecial("CATPrtResultWithOutLink")
new_part_doc.Part.Update()
new_extract = new_hb.HybridShapes.Item(new_hb.HybridShapes.Count)
# Redo changes in the part, where the selection was made
c_sel.Clear()
c_sel.Add(hb)
c_sel.Delete()
# Create axis systems from Position object of sel_prd_by_user and sel_prd_by_catia
prod_list = [sel_prod_by_user, sel_prod_by_catia]
axs_list = []
for prod in prod_list:
pc_pos = pycatia.in_interfaces.position.Position(prod.Position) # conversion to pycata's Position object, necessary
# in order to use Position.GetComponents
ax_comp = pc_pos.get_components()
axs = new_part_doc.Part.AxisSystems.Add()
axs.PutOrigin(ax_comp[9:12])
axs.PutXAxis(ax_comp[0:3])
axs.PutYAxis(ax_comp[3:6])
axs.PutZAxis(ax_comp[6:9])
axs_list.append(axs)
new_part_doc.Part.Update()
# Translate the extract from axis system derived from sel_prd_by_catia to sel_prd_by_user
extract_ref = new_part_doc.Part.CreateReferenceFromObject(new_extract)
tgt_ax_ref = new_part_doc.Part.CreateReferenceFromObject(axs_list[0])
ref_ax_ref = new_part_doc.Part.CreateReferenceFromObject(axs_list[1])
new_extract_translated = new_part_doc.Part.HybridShapeFactory.AddNewAxisToAxis(extract_ref, ref_ax_ref, tgt_ax_ref)
new_hb.AppendHybridShape(new_extract_translated)
new_part_doc.Part.Update()
I would suggest a differed approach. Instead of adding references you get from somewhere (by name probably) add the actual instance of part to selection while iterating trough all the products. Or use instance Names to get the correct part.
Here is a simple VBA example of iterating one lvl tree and select copy paste scenario.
If you want to copy features, you have to dive deeper on the Instance objects.
Public Sub CatMain()
Dim ActiveDoc As ProductDocument
Dim ActiveSel As Selection
If TypeOf CATIA.ActiveDocument Is ProductDocument Then 'of all the checks that people are using I think this one is most elegant and reliable
Set ActiveDoc = CATIA.ActiveDocument
Set ActiveSel = ActiveDoc.Selection
Else
Exit Sub
End If
Dim Instance As Product
For Each Instance In ActiveDoc.Product.Products 'object oriented for ideal for us in this scenario
If Instance.Products.Count = 0 Then 'beware that products without parts have also 0 items and are therefore mistaken for parts
Call ActiveSel.Add(Instance)
End If
Next
Call ActiveSel.Copy
Call ActiveSel.Clear
Dim NewDoc As ProductDocument
Set NewDoc = CATIA.Documents.Add("CATProduct")
Set ActiveSel = NewDoc.Selection
Call ActiveSel.Add(NewDoc.Product)
Call ActiveSel.Paste
Call ActiveSel.Clear
End Sub
I want to create some code in TabPy that will count the frequency of words in a column and remove stop words for a word cloud in Tableau.
I'm able to do this easily enough in Python:
other1_count = other1.answer.str.split(expand=True).stack().value_counts()
other1_count = other1_count.to_frame().reset_index()
other1_count.columns = ['Word', 'Count']
### Remove stopwords
other1_count['Word'] = other1_count['Word'].apply(lambda x: ' '.join([word for word in x.split() if word not in (stop)]))
other1_count['Word'].replace('', np.nan, inplace=True)
other1_count.dropna(subset=['Word'], inplace=True)
other1_count = other1_count[~other1_count.Word.str.contains("nan")]
But less sure how to run this through TabPy. Anyone familiar with TabPy and how I can make this run?
Thanks in advance.
I worked on a project that accomplished something very similar a while back in R. Here's a video example showing the proof-of-concept (no audio). https://www.screencast.com/t/xa0yemiDPl
It essentially shows the end state of using Tableau to interactively examine the description of wines in a word-cloud for the selected countries. The key components were:
have Tableau connect to the data to analyze, as well as a placeholder dataset that has the number of records you expect to get back from your Python/R code (the call out to Python/R from Tableau expects to get back the same number of records it sends off to process... that can be problematic if your sending text data, but processing it to return back many more records - as would be the case in the word cloud example)
have the Python/R code connect to your data and return the Word and Frequency counts in a single vector, separated by a delimiter (what Tableau will require for a word cloud)
split the single vector using Tableau Calculated Fields
leverage parameter actions to select parameter values to pass to the Python/R code
High-Level Overview
Tableau Calculated Field - [R Words+Freq]:
Script_Str('
print("STARTING NEW SCRIPT RUN")
print(Sys.time())
print(.arg2) # grouping
print(.arg1) # selected country
# TEST VARIABLE (non-prod)
.MaxSourceDataRecords = 1000 # -1 to disable
# TABLEAU PARAMETER VARIABLES
.country = "' + [Country Parameter] + '"
.wordsToReturn = ' + str([Return Top N Words]) + '
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#
# VARIABLES DERIVED FROM TABLEAU PARAMETER VALUES
.countryUseAll = (.country == "All")
print(.countryUseAll)
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#
#setwd("C:/Users/jbelliveau/....FILL IN HERE...")
.fileIn = ' + [Source Data Path] + '
#.fileOut = "winemag-with-DTM.csv"
#install.packages("wordcloud")
#install.packages("RColorBrewer") # not needed if installed wordcloud package
library(tm)
library(wordcloud)
library(RColorBrewer) # color package (maps or wordclouds)
wineAll = read.csv(.fileIn, stringsAsFactors=FALSE)
# TODO separately... polarity
# use all the data or just the parameter selected
print(.countryUseAll)
if ( .countryUseAll ) {
wine = wineAll # filter down to parameter passed from Tableau
}else{
wine = wineAll[c(wineAll$country == .country),] # filter down to parameter passed from Tableau
}
# limited data for speed (NOT FOR PRODUCTION)
if( .MaxSourceDataRecords > 0 ){
print("limiting the number of records to use from input data")
wine = head(wine, .MaxSourceDataRecords)
}
corpus = Corpus(VectorSource(wine$description))
corpus = tm_map(corpus, tolower)
#corpus = tm_map(corpus, PlainTextDocument) # https://stackoverflow.com/questions/32523544/how-to-remove-error-in-term-document-matrix-in-r/36161902
corpus = tm_map(corpus, removePunctuation)
corpus = tm_map(corpus, removeWords, stopwords("English"))
#length(corpus)
dtm = DocumentTermMatrix(corpus)
#?sample
mysample = dtm # no sampling (used Head on data read... for speed/simplicity on this example)
#mysample <- dtm[sample(1:nrow(dtm), 5000, replace=FALSE),]
#nrow(mysample)
wineSample = as.data.frame(as.matrix(mysample))
# column names (the words)
# use colnames to get a vector of the words
#colnames(wineSample)
# freq of words
# colSums to get the frequency of the words
#wineWordFreq = colSums(wineSample)
# structure in a way Tableau will like it
wordCloudData = data.frame(words=colnames(wineSample), freq=colSums(wineSample))
str(wordCloudData)
# sort by word freq
wordCloudDataSorted = wordCloudData[order(-wordCloudData$freq),]
# join together by ~ for processing once Tableau gets it
wordAndFreq = paste(wordCloudDataSorted[, 1], wordCloudDataSorted[, 2], sep = "~")
#write.table(wordCloudData, .fileOut, sep=",",row.names=FALSE) # if needed for performance refactors
topWords = head(wordAndFreq, .wordsToReturn)
#print(topWords)
return( topWords )
',
Max([Country Parameter])
, MAX([RowNum]) // for testing the grouping being sent to R
)
Tableau Calculated Field for the Word Value:
// grab the first token to the left of ~
Left([R Words+Freq], Find([R Words+Freq],"~") - 1)
Tableau Calculated Field for the Frequency Value:
INT(REPLACE([R Words+Freq],[Word]+"~",""))
If you're not familiar with Tableau, you'll likely want to work alongside a Tableau analyst at your company that is. They'll be able to help you create the calculated fields and configure Tableau to connect to TabPy.
I think that the best way to get familiar with Python related to Tableau could be this (old) thread on the Tableau community:
https://community.tableau.com/s/news/a0A4T000002NznhUAC/tableau-integration-with-python-step-by-step?t=1614700410778
It explains step-by-step the initial set up and how to "call" Python via Tableau Calculated fields.
In addition, you'll find at the top of the post the reference to the more updated TabPy GitHub repository:
https://github.com/tableau/TabPy
taxNo = arcpy.GetParameterAsText(0)
thisMap = arcpy.mapping.MapDocument("CURRENT")
myDF = arcpy.mapping.ListDataFrames(thisMap)[0]
myLayers = arcpy.mapping.ListLayers(myDF)
for lyr in myLayers:
if lyr.name == "Address Numbers":
arcpy.SelectLayerByAttribute_management(lyr,"NEW_SELECTION","EKEY = " + taxNo[0])
for tax in taxNo:
arcpy.SelectLayerByAttribute_management(lyr,"ADD_TO_SELECTION","EKEY = " + tax)
arcpy.AddWarning("Additional Selection " + tax)
I'm trying to build a script in ArcGIS that will select a series of user defined values, in this case I'm trying to select 1784102 and 1784110. When I use arcpy.AddWarning(taxNo) before the loop, I get the output "1784102;1784110" but it's iterating through it one number at a time i.e.
Additional Selection 1
Additional Selection 7
Additional Selection 8
Additional Selection 4
etc.
then pops up an error when it hits the semi-colon.
The parameters for taxNo are set up in ArcMap as a String, Multivalue, Valuelist.
I will just assume you are calling your script like this:
python script.py 1784102;1784110
Your variable taxNo = arcpy.GetParameterAsText(0) then is a single string "1784102;1784110". If you use "array indexes" on strings (for example taxNo[0], taxNo[1] etc.) you are getting single characters out of that string, i.e. "1", "7", "8" ...
Call .split(';') to your arcpy.GetParameterAsText(0) result to split the string "1784102;1784110" into an array of two strings: ["1784102", "1784110"]. If you need a numeric item, i.e. integers, try this too.
taxNo = arcpy.GetParameterAsText(0).split(';')