Module 4 - Hazards: Coastal Flooding

     This week's module focused on the necessary procedures for coastal flooding assessment. Using DEMs, we assessed destruction, storm surge/flood risk and flood zones.


    I created this map starting from USGS and LiDAR DEM rasters by using various geoprocessing tools, including the Reclassify tool and the Region Group tool. This map omits low-lying areas that were not connected to the larger USGS/LiDAR DEMs. Exclusion of these low-lying disconnected areas could lead to an underestimation of storm surge risk. These areas could still flood if they are connected through drainage systems. Hydrological modeling could help identify flow paths of watersheds to help with increasing accuracy in the assessment of flood risk.

Module 3 - Visibility Analysis

     This week's module involved completing select courses from the "Get Started with Visibility Analysis" Esri Learning Plan. I learned the difference between the different elevation types (on ground, relative to ground, and absolute height) from the "Introduction to 3D Visualization" course. The course also offered examples of extrusion types for 3D symbology, such as polygon features being extruded vertically to represent buildings.

    The "Performing Line of Sight Analysis" course listed the inputs required for performing a line of sight analysis, and described the workflow for doing so. The image below is one of the example images used in the course, where the green lines represent areas that are visible, and the red lines represent areas not visible. The course also described how to use the Construct Sight Lines and Line of Sight tools.

 

    The "Performing Viewshed Analysis in ArcGIS Pro" course describes how to create an output raster that represents the visible area from an observer point, similar to the previous course. The main difference between the two analyses is that the Line of Sight analysis determines obstructed and unobstructed view along a line, and the Viewshed analysis symbolizes an area as visible or not visible. This course instructed me on how to use the Viewshed tool.

    The final course, "Sharing 3D Content Using Scene Layer Packages" mainly taught me how to create and use Scene Layer Packages.

Module 2 - LiDAR

    This week's module focused on how to generate DEM's, DSM's, and tree heights and densities from LiDAR data. The study area for this module is the Shenandoah National Park located in Virginia. This module introduced me to working with LAS datasets and LAS-related ArcGIS tools such as the LAS to MultiPoint tool or the LAS Dataset to Raster tool. 

    This layout contains the LiDAR scene as well as the DSM I had generated.


    This layout depicts the tree height distribution in the quadrant. The graph tells us that most of the trees in the area are 54.69 ± 20.55 ft in height. There are very few trees taller than 90 ft in the area. There are a few “trees” with negative values, but these can be attributed to the man made features in the area.

 

    And this is a layout of the canopy density of the quadrant. This layout clearly depicts the man-made features such as Skyline Dr to the east.

Module 1 - Crime Analysis

  The topic of this course's first module was hotspot analysis. We were tasked to make three maps of 2017 Chicago homicides using local clustering. The three methods used were grid-based mapping, kernel density and local Moran's I.


   From left to right: grid-based, kernel density and local Moran's I.

   The steps I took to create these maps were as follows:

Grid-based

     First, I used the Spatial Join Tool to join the overlaid grid with the 2017 homicides feature layers. Then, from the grids that contained greater than 0 homicides I exported the top quintile into a new feature layer. I used the Dissolve Tool to finalize the grid-based map.

 Kernel Density

    I started by using the Kernel Density Tool on the 2017 homicides point feature layer. I changed the output feature to consist of 2 classes and used the Reclassify Tool. Lastly I used Select By Attributes to export the gridcode 2 features to use as the final map.

Local Moran's I

    The first step was to use the Spatial Join Tool to join the census tracts and 2017 homicide features. After, I used the Cluster and Outlier Analysis (Local Moran's I) Tool on the spatially joined features using a calculated Crime Rate field. To finalize the map I used the Dissolve Tool to dissolve previously exported HH features.

GIS 5100: Applications in GIS Intro Post

My name is Keanu, I was born and raised in Suriname and I am a Dutch-English bilingual. I have a Bachelor's degree in Biological Science, obtained from Florida State University in Tallahassee. I am currently employed full time with the Florida DEP's Division of Environmental Assessment and Restoration as an Environmental Specialist I, where I assist in monitoring the state's water quality. We analyze water samples obtained from all across the state for microbiological indicators.

I joined the GIS Master's Program because I wanted to tie in the experience I have gained in the environmental field along with my computer skills. I hope to achieve my master's degree in GIS Administration by the end of 2026.

 Please find a link to my story map here: https://arcg.is/1LDnvC

Module 6 - Working with Geometries: Extracting Vertex Coordinates from Line Features

The final module of GIS Programming had us write a script that extracts every vertex from a set of river/stream line features (Hawaii stream data) and writes them out to a text file. One line per vertex, containing the feature's OID, a vertex ID, the X/Y coordinates, and the stream's name.

The core of the script is a nested loop: an outer SearchCursor loop iterates over each river feature (row), and an inner loop walks through every point in that feature's geometry (row[1].getPart(0)), incrementing a vertex counter as it goes. For each vertex, I built a formatted string with the OID, vertex ID, coordinates, and stream name, then wrote it to a text file and printed it to the console for verification. 


I hit one bug worth mentioning: I initially tried to pull the river's name using "NAME@" as the cursor field, which failed. The @ suffix in arcpy cursor fields is reserved for special geometry/identity tokens like "OID@" and "SHAPE@." NAME is a normal attribute field, not one of those tokens, so it just needed to be "NAME" on its own. It was a quick fix once I understood why it failed, instead of just matching a pattern I'd seen elsewhere in the script.

One small habit from this module I've kept since: instead of writing the output string directly into both the write() and print() calls, I assigned it to a single variable (txtFormula) first and used that variable in both places. That way, if I needed to change the output format while debugging, I only had to edit one line instead of keeping two copies in sync.



Module 5 - Exploring & Manipulating Data

This module's script had three parts: create a new file geodatabase, copy an existing set of shapefiles into it, then use search cursors to extract and reorganize data from one of those feature classes. First as a filtered printout, then as a populated dictionary.


The first part used CreateFileGDB_management() to create the geodatabase, then looped through every feature class in the source workspace with CopyFeatures_management(), printing a success message and elapsed time for each copy, which is useful for confirming nothing silently failed partway through a batch operation.


The second part used a SearchCursor with an embedded SQL where-clause to pull only the "County Seat" features out of a cities shapefile, printing each city's name, feature type, and circa-2000 population. One thing I noticed working with the data: a few cities show a population of -99999, which is a placeholder for missing/unavailable data rather than an actual value, which is worth flagging if this feature class were used downstream, since a naive average or sum would be badly skewed by it.


This part of the script uses SQL within the SearchCursor to only search for County Seat feature types within the cities attribute table. Using row.getValue() and defined variables, I was able to print each set of data. Below is a summarized flowchart of this section of the script.


The third part is where I hit the most interesting bug of the module. I needed to populate a dictionary (county_seats) using the same cursor logic, but it kept returning an empty dictionary. My first guess was a workspace path issue, which I fixed, but the dictionary still only returned a single entry ({'Carlsbad': 25625}) instead of the full set. I'd assumed that deleting the cursor's current row (del row) was sufficient cleanup between cursor uses, but the real issue was that I hadn't deleted the cursor object itself. Python was holding onto the exhausted cursor from the previous step, so the new loop had nothing left to iterate over. Once I deleted the cursor properly and re-created a fresh one for this step, the dictionary populated correctly with all city entries.


I ended up using the <dictionary_variable>[key] = value method to populate the county_seats dictionary. This final part of the script has a similar flowchart as part B does.

 

I also split one long print statement across multiple concatenated lines (city name / feature type / population) for readability. It was a small style choice, but one that made the script easier to scan when I came back to it later.


 

Module 4 - Geoprocessing

    This module's task was to build a Python script that runs a small spatial analysis pipeline on a hospitals shapefile: add XY coordinates, generate a buffer around each point, and dissolve the resulting buffers into a single feature.

    I structured the script in three stages. First, I used Copy_management() to duplicate the original hospitals shapefile before making any changes as I wanted the source data to stay untouched in case I needed to re-run or compare against it later. Then AddXY_management() added coordinate fields to the copy. Second, arcpy.analysis.Buffer() created a 1000-foot buffer around each hospital point. Third, arcpy.management.Dissolve() merged the buffers into a single output feature. I added arcpy.GetMessages() after each step so I could confirm success (or catch failures) at every stage. The terminal output below shows each step completing with its execution time.

 

    I originally used arcpy.management.Delete() to manually clear old outputs so I could re-run the script during testing. I realized that was the wrong tool as 'arcpy.env.overwriteOutput = True' does this automatically and is the standard way to allow geoprocessing outputs to be overwritten during iterative testing, so I switched to that instead.


Module 7 - Google Earth

     This final module focused on creating Google Earth maps and tours, as well as converting ArcGIS maps to the KML format. Starting off with a surface water feature layer, I used the "Layer to KML" geoprocessing tool to convert my map into a .kmz file for use in Google Earth. I then imported my converted file as well as the other provided .kmz files into Google Earth.


        I then created a tour of South Florida using the "Record a Tour" button through placemarks I added. I had some trouble navigating Google Earth as I am used to the inverse x and y camera controls.