Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
Signed-off-by: Filip Kral
  • Loading branch information
unknown authored and unknown committed Feb 24, 2014
1 parent 5311aef commit ddebabb
Show file tree
Hide file tree
Showing 57 changed files with 1,523 additions and 0 deletions.
1,123 changes: 1,123 additions & 0 deletions arcapi.py

Large diffs are not rendered by default.

268 changes: 268 additions & 0 deletions arcapi_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,268 @@
"""
#-------------------------------------------------------------------------------
# Name: arcapi_test
# Purpose: Tests for arcapi module.
#
# Author: Filip Kral
#
# Created: 01/02/2014
# Licence: LGPL v3
#-------------------------------------------------------------------------------
# Most of the functions operate on potentially complex data, or require manual
# checking of results, and therefore testing is rather difficult.
#
# Everybody is encouraged to contribute to tests.
#-------------------------------------------------------------------------------
"""

import unittest
import os
import sys
import arcpy
import arcapi as ap

class TestGlobalFunctions(unittest.TestCase):

def setUp(self):
# access testing data
self.testing_gdb = os.path.join(os.path.dirname(os.path.realpath(__file__)), r'testing\testing.gdb')
#self.t_table = os.path.join(self.testing_gdb, '\left_i_right')
#self.t_fc = os.path.join(self.testing_gdb, 'left_i_right')
#self.t_cols = ('OBJECTID', 'Shape', 'CCARM2', 'POINT_X', u'POINT_Y', u'ROUND_X', 'ROUND_Y', 'name', 'propagatedName', 'fullName', 'GID', 'DOWNGID', 'HA_NUM','STRAHLER', 'SHREVE', 'OS_NAME', 'FNODE_FULL', 'TNODE_FULL', 'NAMENOXML', 'Shape_Length')
self.t_fc = os.path.join(self.testing_gdb, 'ne_110m_admin_0_countries')
self.t_cols = ('OBJECTID','Shape','ScaleRank','LabelRank','FeatureCla',
'SOVEREIGNT','SOV_A3','ADM0_DIF','LEVEL','TYPE','ADMIN',
'ADM0_A3','GEOU_DIF','GEOUNIT','GU_A3','SU_DIF','SUBUNIT',
'SU_A3','NAME','ABBREV','POSTAL','NAME_FORMA','TERR_',
'NAME_SORT','MAP_COLOR','POP_EST','GDP_MD_EST','FIPS_10_',
'ISO_A2','ISO_A3','ISO_N3','Shape_Length','Shape_Area')
pass

def tearDown(self):
pass

def testnames(self):
est = map(str, tuple(ap.names(self.t_fc)))
obs = ('OBJECTID','Shape','ScaleRank','LabelRank','FeatureCla',
'SOVEREIGNT','SOV_A3','ADM0_DIF','LEVEL','TYPE','ADMIN',
'ADM0_A3','GEOU_DIF','GEOUNIT','GU_A3','SU_DIF','SUBUNIT',
'SU_A3','NAME','ABBREV','POSTAL','NAME_FORMA','TERR_',
'NAME_SORT','MAP_COLOR','POP_EST','GDP_MD_EST','FIPS_10_',
'ISO_A2','ISO_A3','ISO_N3','Shape_Length','Shape_Area')
self.assertEqual(tuple(est), obs)
pass

def testtypes(self):
est = map(str, tuple(ap.types(self.t_fc)))
obs = ('OID','Geometry','SmallInteger','SmallInteger','String','String',
'String','Single','Single','String','String','String','Single',
'String', 'String','Single','String','String','String','String',
'String','String', 'String','String','Single','Double','Double',
'Single','String','String', 'Single','Double','Double')
pass

def testnrow(self):
est = ap.nrow(self.t_fc)
obs = 177
self.assertEqual(est, obs)
pass

## def testvalues(self):
## pass
##
## def testdistinct(self):
## pass

def testhead(self):
est = 5
hd = ap.head(self.t_fc, est, geoms = " ", verbose=False)
obs = len(hd[0])
self.assertEqual(est, obs)
pass

def testchart(self):
obs = r'c:\temp\chart.jpg'
t_fc = self.t_fc
est = ap.chart(t_fc, obs, texts = {'txt': 'Element txt'}, openit=False)
self.assertEqual(est, obs)
pass

def testplot(self):
pic = r'c:\temp\plot.png'
x = xrange(20)
ap.plot(x, out_file=pic, openit=False)
y = xrange(50,70)
ap.plot(x, y, pic, 'Main', 'X [m]', 'Y [m]', 'o', 'k', openit=False)
os.remove(pic)
with self.assertRaises(ap.ArcapiError):
ap.plot(x, [1,2,3], pic, 'Main', 'X [m]', 'Y [m]', 'o', 'k', openit=False)
pass

def testrename_col(self):
import arcpy
import tempfile
owo = arcpy.env.overwriteOutput
arcpy.env.overwriteOutput = True
tmpfc = os.path.join(tempfile.gettempdir(), "tmp")
tmpfc = arcpy.CopyFeatures_management(self.t_fc, tmpfc).getOutput(0)
est = ap.rename_col(tmpfc, "ABBREV", "ABBREVIATION")
obs = "ABBREVIATI"
arcpy.Delete_management(tmpfc)
arcpy.env.overwriteOutput = owo
self.assertEqual(est, obs)
pass

def testtlist_to_table(self):
ot = arcpy.CreateScratchName('tmp.dbf', workspace='c:\\temp')
colnames = ['NAME', 'POP_EST']
coltypes = ['TEXT', 'DOUBLE']
collengths = [250, '#']
coldefs = zip(colnames, coltypes, collengths)

# read data
tl = []
with arcpy.da.SearchCursor(self.t_fc, colnames) as sc:
for row in sc:
tl.append(tuple(row))

# write as table
ot = ap.tlist_to_table(tl, ot, coldefs, -9, 'nullText')
ap.head(ot)
est = int(arcpy.GetCount_management(ot).getOutput(0))
obs = int(arcpy.GetCount_management(self.t_fc).getOutput(0))

arcpy.Delete_management(ot)
self.assertEqual(est, obs)
pass

## def testdocu(self):
## pass

def testmeta(self):
fcws = 'c:\\temp'
fcnm = os.path.basename(arcpy.CreateScratchName('tmp.shp', workspace=fcws))

fc = arcpy.FeatureClassToFeatureClass_conversion(
self.t_fc,
fcws,
fcnm
).getOutput(0)

ap.meta(fc, 'OVERWRITE', title="Bar")
ap.meta(fc, 'append', purpose='example', abstract='Column Spam means eggs')

ap.dlt(fc)
pass

## def testmsg(self):
## pass

def testfrequency(self):
est = ap.frequency([1,1,2,3,4,4,4])
obs = {1: 2, 2: 1, 3: 1, 4: 3}
samekeys = set(est.keys()) == set(obs.keys())
good = all([samekeys] + [est[i] == obs[i] for i in est])
self.assertTrue(good)
pass

def testlist_environments(self):
envs = ap.list_environments([])
self.assertEqual(len(envs), 50)
pass

def testoidF(self):
est = ap.oidF(self.t_fc)
obs = "OBJECTID"
self.assertEqual(str(est), obs)
pass

def testshpF(self):
est = ap.shpF(self.t_fc)
obs = "Shape"
self.assertEqual(str(est), obs)
pass

def testtstamp(self):
est = []
est.append(len(ap.tstamp()) == len('20140216184029'))
est.append(len(ap.tstamp("lr")) == len('lr20140216184045'))
est.append(len(ap.tstamp("lr", "%H%M%S")) == len('lr184045'))
est.append(len(ap.tstamp("lr", "%H%M%S")) == len('lr184045'))
est.append(len(ap.tstamp("lr", "%H%M%S", s=('run',1))) == len('lr184527_run_1'))
obs = [True, True, True, True, True]
self.assertEqual(est, obs)
pass

def testdlt(self):
est = []
wc = '"OBJECTID" < 11'
lr = arcpy.management.MakeFeatureLayer(self.t_fc, "lr", wc).getOutput(0)
# TODO: test for deleting layers won't pass even though ap.dlt works
#print lr
#print arcpy.Exists(lr)
tempfc = 'in_memory\\tmp'
if arcpy.Exists(tempfc):
arcpy.Delete_management(tempfc)
tmpfc = arcpy.CopyFeatures_management(lr, tempfc).getOutput(0)
fc = arcpy.CopyFeatures_management(tmpfc, arcpy.CreateScratchName("tmp.shp", workspace="c:\\temp")).getOutput(0)
ap.dlt(lr)
est.append(ap.dlt(tmpfc))
est.append(ap.dlt(fc))
est.append(ap.dlt('this does not exist'))
self.assertEquals(est, [True, True, False])
pass

def testcleanup(self):
x = []
out = arcpy.CreateScratchName("tmp", workspace=arcpy.env.scratchGDB)
x.append(arcpy.management.Copy(self.t_fc, out).getOutput(0))
est = ap.cleanup(x)
obs = 0
self.assertEqual(est, obs)

def testto_points(self):
obs = 10
wc = '"OBJECTID" < ' + str(obs + 1)
ofc = arcpy.CreateScratchName("tmp_out.shp", workspace="c:\\temp")
cs = 27700
ptfc = ap.to_points(self.t_fc, ofc, "POP_EST", "GDP_MD_EST", cs, w = wc)
est = int(arcpy.GetCount_management(ptfc).getOutput(0))
arcpy.Delete_management(ptfc)
self.assertEqual(est, obs)
pass


## def testwsp(self):
## pass
##
## def testswsp(self):
## pass

def testto_scratch(self):
est = []
obs = []
arcpy.env.scratchWorkspace = arcpy.env.scratchGDB
s = arcpy.env.scratchWorkspace

est.append(ap.to_scratch('foo', 0))
obs.append(ap.os.path.join(s, 'foo'))
est.append(ap.to_scratch('foo', 1))
obs.append(os.path.join(s, 'foo0'))
est.append(ap.to_scratch('foo.shp', 0))
obs.append(os.path.join(s, 'foo_shp'))
est.append(ap.to_scratch('foo.shp', 1))
obs.append(os.path.join(s, 'foo_shp0'))

# not tested for file based workspaces
arcpy.env.scratchWorkspace = arcpy.env.scratchFolder
a = arcpy.env.scratchWorkspace
ap.to_scratch('foo', 0) == os.path.join(s, 'foo')
ap.to_scratch('foo', 1) == os.path.join(s, 'foo0')
ap.to_scratch('foo.shp', 0) == os.path.join(s, 'foo_shp')
ap.to_scratch('foo.shp', 1) == os.path.join(s, 'foo_shp0')

eq = all([ei == oi for ei,oi in zip(est, obs)])
self.assertTrue(eq)

if __name__ == '__main__':
unittest.main(verbosity = 2)
130 changes: 130 additions & 0 deletions arcapi_tutorial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
"""
#-------------------------------------------------------------------------------
# Name: arcapi_tutorial
# Purpose: Tutorial for arcapi module.
#
# Author: Filip Kral
#
# Created: 20/02/2014
# Licence: LGPL v3
#-------------------------------------------------------------------------------
# This tutorial shows how to use some functions from the arcapi module
# to explore a dataset in a terminal, PyScripter, or what have you.
#-------------------------------------------------------------------------------
"""

# import the usual module(s)
import arcpy, sys, os
# If you don't have arcapi.py in your path, you can add it like so:
sys.path.insert(0, r'c:\path\to\directory\with_arcapi_dot_py')
# import arcapi using the recommended alias
import arcapi as ap


# Set environment settings, at least workspace.
# base.gdb will be created if it doesn't exist.
ap.wsp('c:\\temp\\base.gdb')
# If you are in ArcMap and want to override the
# default scratch workspace too, call e.g.
ap.swsp(ap.wsp())

# We will work with the famous meuse dataset of soil
# properties from about 150 points near river Meuse
# collected near city Stein in The Netherlands.
# The meuse dataset can be downloaded from the Internet.
# You can download it directly from Python using urllib2
# and save it as a text file onto your hard drive like so:
url= 'https://raw.github.com/filipkral/meuse/master/meuse.txt'
text = os.path.join(arcpy.env.scratchFolder, 'meuse.txt')
import urllib2
ur = urllib2.urlopen(url)
with open(text, 'w') as tx:
tx.write(ur.read())
ur.close()

# We have our data in a text file, which we need to import
# into ArcGIS native format, ideally Esri File Geodatabase.
# ap has short name tviw for arcpy.management.CreateTableView,
# flyr and rlyr for CreateFeatureLayer and CreateRasterLayer.
tb = ap.tviw(text, "tb")
# check that the names and data types are what you would expect
ap.names(tb)
ap.types(tb)
# or maybe:
zip(ap.names(tb), ap.types(tb))

# It is point data so let's convert it to a point feature class.
# Store it as a point feature class called 'dta' in our base.gdb.
fc = ap.to_points(tb, ap.to_scratch('dta'), 'x', 'y', 28992)
tmp = ap.head(fc)
# We don't need the table view of text any more so get rid of it.
ap.dlt(tb)
# And we don't need the text file itself either so get rid of it.
ap.dlt(text)
# Print first 10 records using default settings (columns as rows)
tmp = ap.head(fc)
# now print 5 rows as a formatted table, print '-' for geometries
tmp = ap.head(fc, 5, False, '|', '-')

# Print some basic statistics for each column.
tmp = ap.summary(fc)
# Force lime, soil, and ffreq to be treated as categorical variables.
tmp = ap.summary(fc, ['lime', 'soil', 'ffreq'], ['CAT', 'CAT', 'CAT'])


# Make a quick map
# If you are in ArcMap's Python window, add fc as a feature layer.
# This will add the layer if your ArcMap's Geoprocessing options
# allow to 'Add results of geoprocessing operations to the display'.
ap.flyr(fc)
# If you are not in ArcMap, you can still plot the feature class:
ap.chart(fc)


# You can plot values in a column once you read its values into Python.
# Let's first find out what unique landuse categories there are in fc:
ap.distinct(fc, 'landuse')
# How many records of each species are there?
x = ap.values(fc, 'landuse')
ap.frequency(x)

# Now plot zinc concentration for landuse 'W'
z = ap.values(fc, 'zinc', '"landuse" = \'W\'', '"OBJECTID" ASC')
ap.plot(z)
# Show scatter plot of zinc against distance from the river
# The 'order by' clause ensures values come in the same order
d = ap.values(fc, 'dist_m', '"landuse" = \'W\'', '"OBJECTID" ASC')
ap.plot(d, z, main='Zinc', xlab='Ditance', ylab='Zn', pch='o', color='k')


# Suppose we want to add full labels indicating landuse at points.
# This can come as a table, json, or other forms. Anyhow, we would
# convert it to a Python dictionary. I simply re-typed help of 'sp':
# http://cran.r-project.org/web/packages/sp/sp.pdf
landuse2luse = {
'Aa': 'Agriculture/unspecified', 'Ab': 'Agr/sugar beetsm',
'Ag': 'Agr/small grains', 'Ah': 'Agr/??', 'Am': 'Agr/maize', 'B': 'woods',
'Bw': 'trees in pasture', 'DEN': '??', 'Fh': 'tall fruit trees',
'Fl': 'low fruit trees', 'Fw': 'fruit trees in pasture',
'Ga': 'home gardens', 'SPO': 'sport field', 'STA': 'stable yard',
'Tv': '??', 'W': 'pasture'
}
# now we need to add a column for these labels
ap.add_col(fc, 'luse', 'TEXT')
# and update the column with landuse dictionary:
# (If you're in ArcMap and fc's attribute table is open,
# you will need to Reload Cache in Table Options.)
ap.update_col_from_dict(fc, landuse2luse, 'luse', 'landuse')

# So why didn't we use table join to do this?
# You could, especially if you have Advanced
# license so you can use JoinFied_management.
# With Basic license, it is much easier to use
# ap.update_col_from_dict, which is also pretty
# fast with its update cursor.

# Finally, make a note about this update to metadata of fc
ap.meta(fc, 'APPEND', abstract='Updated at ' + ap.tstamp())

# To list all functions available in arcapi and their help:
help(ap)
Binary file added chart.mxd
Binary file not shown.
Loading

1 comment on commit ddebabb

@CalebM1987
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can I contribute code to this module?

Please sign in to comment.