From 61b1e881e481292086c4c2d70295ecb603a91532 Mon Sep 17 00:00:00 2001 From: Doug Morgenthaler Date: Mon, 22 Jun 2026 07:27:56 -0700 Subject: [PATCH 01/13] Add new metadata fields --- notebooks/Add GPS Metadata Fields_FS.ipynb | 405 ++++++++++++++++++--- 1 file changed, 363 insertions(+), 42 deletions(-) diff --git a/notebooks/Add GPS Metadata Fields_FS.ipynb b/notebooks/Add GPS Metadata Fields_FS.ipynb index eb326a3..b4ce66a 100644 --- a/notebooks/Add GPS Metadata Fields_FS.ipynb +++ b/notebooks/Add GPS Metadata Fields_FS.ipynb @@ -24,6 +24,7 @@ " - `item_id`\n", " - `feature_layer_index`\n", " - `include_offset_fields`\n", + " - `include_tilt_fields`\n", "2. Run all cells\n" ] }, @@ -42,6 +43,7 @@ "item_id = \"7984f1a3089c47eaad07086b19f6fe92\" # item_id of feature layer\n", "feature_layer_index = 0 #index of layer you want to update\n", "include_offset_fields = False # indicate if you want offset fields added (point feature layers only)\n", + "include_tilt_fields = False # indicate if you want tilt fields added (point feature layers only)\n", "\n", "gis = GIS(org_url, username)" ] @@ -203,6 +205,20 @@ " 'domain': None,\n", " 'defaultValue': None})\n", "else:\n", + " # esrignss_receiver\n", + " receiver_field = [field for field in feature_layer_fields if field['name'].lower() == 'esrignss_receiver']\n", + " \n", + " if not receiver_field:\n", + " gnss_metadata_fields['fields'].append({'name': 'esrignss_receiver',\n", + " 'type': 'esriFieldTypeString',\n", + " 'alias': 'Receiver name',\n", + " 'sqlType': 'sqlTypeOther',\n", + " 'length': 50,\n", + " 'nullable': True,\n", + " 'editable': True,\n", + " 'domain': None,\n", + " 'defaultValue': None})\n", + "\n", " # esrignss_positionsourcetype\n", " positionsourcetype_field = [field for field in feature_layer_fields if field['name'].lower() == 'esrignss_positionsourcetype']\n", "\n", @@ -241,20 +257,6 @@ " {'name': 'Snapped', 'code': 5}]},\n", " 'defaultValue': None})\n", "\n", - " # esrignss_receiver\n", - " receiver_field = [field for field in feature_layer_fields if field['name'].lower() == 'esrignss_receiver']\n", - " \n", - " if not receiver_field:\n", - " gnss_metadata_fields['fields'].append({'name': 'esrignss_receiver',\n", - " 'type': 'esriFieldTypeString',\n", - " 'alias': 'Receiver name',\n", - " 'sqlType': 'sqlTypeOther',\n", - " 'length': 50,\n", - " 'nullable': True,\n", - " 'editable': True,\n", - " 'domain': None,\n", - " 'defaultValue': None})\n", - "\n", " # esrignss_latitude\n", " latitude_field = [field for field in feature_layer_fields if field['name'].lower() == 'esrignss_latitude']\n", "\n", @@ -294,6 +296,18 @@ " 'domain': None,\n", " 'defaultValue': None})\n", "\n", + " # esrignss_orthometric_height\n", + " altitude_field = [field for field in feature_layer_fields if field['name'].lower() == 'esrignss_orthometric_height']\n", + "\n", + " if not altitude_field:\n", + " gnss_metadata_fields['fields'].append({'name': 'esrignss_orthometric_height',\n", + " 'type': 'esriFieldTypeDouble',\n", + " 'alias': 'Orthometric height (m)',\n", + " 'sqlType': 'sqlTypeOther',\n", + " 'nullable': True,\n", + " 'editable': True,\n", + " 'domain': None,\n", + " 'defaultValue': None})\n", " # esrignss_h_rms\n", " horizontal_accuracy_field = [field for field in feature_layer_fields if field['name'].lower() == 'esrignss_h_rms']\n", "\n", @@ -370,6 +384,72 @@ " {'name': 'RTK Float', 'code': 5}]},\n", " 'defaultValue': None})\n", "\n", + " # esrignss_numsats\n", + " num_sats_field = [field for field in feature_layer_fields if field['name'].lower() == 'esrignss_numsats']\n", + "\n", + " if not num_sats_field: \n", + " gnss_metadata_fields['fields'].append({'name': 'esrignss_numsats',\n", + " 'type': 'esriFieldTypeInteger',\n", + " 'alias': 'Number of satellites',\n", + " 'sqlType': 'sqlTypeOther',\n", + " 'nullable': True,\n", + " 'editable': True,\n", + " 'domain': None,\n", + " 'defaultValue': None})\n", + "\n", + " # esrignss_correction_source_type\n", + " correction_source_type_field = [field for field in feature_layer_fields if \n", + " field['name'].lower() == 'esrignss_correction_source_type']\n", + "\n", + " if correction_source_type_field:\n", + " # Field does exist; check if the domain is set\n", + " if correction_source_type_field[0]['domain'] == None:\n", + " if ([operation for operation in operations if operation == 'updateDefinition']):\n", + " operations.append('updateDefinition')\n", + "\n", + " corr_source_type_field_index = feature_layer_fields.index(correction_source_type_field[0])\n", + " corr_source_type_domain = {'type': 'codedValue',\n", + " 'name': 'esrignss_correction_source_type',\n", + " 'codedValues': [{'name': 'Unknown', 'code': 'Unknown'},\n", + " {'name': 'Direct IP', 'code': 'Direct IP'},\n", + " {'name': 'NTRIP', 'code': 'NTRIP'},\n", + " {'name': 'PPP', 'code': 'PPP'},\n", + " {'name': 'Radio', 'code': 'Radio'},\n", + " {'name': 'SBAS', 'code': 'SBAS'}]}\n", + " feature_layer_fields[corr_source_type_field_index]['domain'] = corr_source_type_domain\n", + "\n", + " else:\n", + " gnss_metadata_fields['fields'].append({'name': 'esrignss_correction_source_type',\n", + " 'type': 'esriFieldTypeString',\n", + " 'alias': 'Correction source type',\n", + " 'sqlType': 'sqlTypeOther',\n", + " 'length': 25,\n", + " 'nullable': True,\n", + " 'editable': True,\n", + " 'domain': {'type': 'codedValue',\n", + " 'name': 'esrignss_yesno_domain',\n", + " 'codedValues': [{'name': 'Unknown', 'code': 'Unknown'},\n", + " {'name': 'Direct IP', 'code': 'Direct IP'},\n", + " {'name': 'NTRIP', 'code': 'NTRIP'},\n", + " {'name': 'PPP', 'code': 'PPP'},\n", + " {'name': 'Radio', 'code': 'Radio'},\n", + " {'name': 'SBAS', 'code': 'SBAS'}]},\n", + " 'defaultValue': None})\n", + "\n", + " # esrignss_correction_source_name\n", + " corr_source_name_field = [field for field in feature_layer_fields if field['name'].lower() == 'esrignss_correction_source_name']\n", + " \n", + " if not corr_source_name_field:\n", + " gnss_metadata_fields['fields'].append({'name': 'esrignss_correction_source_name',\n", + " 'type': 'esriFieldTypeString',\n", + " 'alias': 'Correction source name',\n", + " 'sqlType': 'sqlTypeOther',\n", + " 'length': 100,\n", + " 'nullable': True,\n", + " 'editable': True,\n", + " 'domain': None,\n", + " 'defaultValue': None})\n", + "\n", " # esrignss_correctionage\n", " correction_age_field = [field for field in feature_layer_fields if field['name'].lower() == 'esrignss_correctionage']\n", "\n", @@ -383,26 +463,27 @@ " 'domain': None,\n", " 'defaultValue': None})\n", "\n", - " # esrignss_stationid\n", - " station_id_field = [field for field in feature_layer_fields if field['name'].lower() == 'esrignss_stationid']\n", - "\n", - " if not station_id_field:\n", - " gnss_metadata_fields['fields'].append({'name': 'esrignss_stationid',\n", - " 'type': 'esriFieldTypeInteger',\n", - " 'alias': 'Station ID',\n", + " # esrignss_ntrip_mount_point\n", + " ntrip_mountpoint_field = [field for field in feature_layer_fields if field['name'].lower() == 'esrignss_ntrip_mount_point']\n", + " \n", + " if not ntrip_mountpoint_field:\n", + " gnss_metadata_fields['fields'].append({'name': 'esrignss_ntrip_mount_point',\n", + " 'type': 'esriFieldTypeString',\n", + " 'alias': 'Ntrip mount point',\n", " 'sqlType': 'sqlTypeOther',\n", + " 'length': 100,\n", " 'nullable': True,\n", " 'editable': True,\n", " 'domain': None,\n", " 'defaultValue': None})\n", "\n", - " # esrignss_numsats\n", - " num_sats_field = [field for field in feature_layer_fields if field['name'].lower() == 'esrignss_numsats']\n", + " # esrignss_stationid\n", + " station_id_field = [field for field in feature_layer_fields if field['name'].lower() == 'esrignss_stationid']\n", "\n", - " if not num_sats_field: \n", - " gnss_metadata_fields['fields'].append({'name': 'esrignss_numsats',\n", + " if not station_id_field:\n", + " gnss_metadata_fields['fields'].append({'name': 'esrignss_stationid',\n", " 'type': 'esriFieldTypeInteger',\n", - " 'alias': 'Number of satellites',\n", + " 'alias': 'Station ID',\n", " 'sqlType': 'sqlTypeOther',\n", " 'nullable': True,\n", " 'editable': True,\n", @@ -487,6 +568,119 @@ " 'domain': None,\n", " 'defaultValue': None})\n", "\n", + " # esrignss_antenna_height\n", + " antenna_height_field = [field for field in feature_layer_fields if field['name'].lower() == 'esrignss_antenna_height']\n", + "\n", + " if not antenna_height_field:\n", + " gnss_metadata_fields['fields'].append({'name': 'esrignss_antenna_height',\n", + " 'type': 'esriFieldTypeDouble',\n", + " 'alias': 'GNSS Antenna height (m)',\n", + " 'sqlType': 'sqlTypeOther',\n", + " 'nullable': True,\n", + " 'editable': True,\n", + " 'domain': None,\n", + " 'defaultValue': None})\n", + "\n", + " # esrignss_receiver_gcs\n", + " corr_source_name_field = [field for field in feature_layer_fields if field['name'].lower() == 'esrignss_receiver_gcs']\n", + " \n", + " if not corr_source_name_field:\n", + " gnss_metadata_fields['fields'].append({'name': 'esrignss_receiver_gcs',\n", + " 'type': 'esriFieldTypeString',\n", + " 'alias': 'Geographic coordinate system',\n", + " 'sqlType': 'sqlTypeOther',\n", + " 'length': 60,\n", + " 'nullable': True,\n", + " 'editable': True,\n", + " 'domain': None,\n", + " 'defaultValue': None})\n", + " \n", + " # esrignss_receiver_gcs_wkid\n", + " receiver_gcs_wkid_field = [field for field in feature_layer_fields if\n", + " field['name'].lower() == 'esrignss_receiver_gcs_wkid']\n", + "\n", + " if not receiver_gcs_wkid_field:\n", + " gnss_metadata_fields['fields'].append({'name': 'esrignss_receiver_gcs_wkid',\n", + " 'type': 'esriFieldTypeInteger',\n", + " 'alias': 'Geographic coordinate system WKID',\n", + " 'sqlType': 'sqlTypeOther',\n", + " 'nullable': True,\n", + " 'editable': True,\n", + " 'domain': None,\n", + " 'defaultValue': None})\n", + " \n", + " # esrignss_receiver_ref_epoch\n", + " reciever_ref_epoch_field = [field for field in feature_layer_fields if field['name'].lower() == 'esrignss_receiver_ref_epoch']\n", + "\n", + " if not reciever_ref_epoch_field:\n", + " gnss_metadata_fields['fields'].append({'name': 'esrignss_receiver_ref_epoch',\n", + " 'type': 'esriFieldTypeDouble',\n", + " 'alias': 'Reference epoch',\n", + " 'sqlType': 'sqlTypeOther',\n", + " 'nullable': True,\n", + " 'editable': True,\n", + " 'domain': None,\n", + " 'defaultValue': None})\n", + " \n", + " # esrignss_profile_has_hor_xform\n", + " has_hor_xform_field = [field for field in feature_layer_fields if \n", + " field['name'].lower() == 'esrignss_profile_has_hor_xform']\n", + "\n", + " if has_hor_xform_field:\n", + " # Field does exist; check if the domain is set\n", + " if has_hor_xform_field[0]['domain'] == None:\n", + " if ([operation for operation in operations if operation == 'updateDefinition']):\n", + " operations.append('updateDefinition')\n", + "\n", + " has_hor_xform_field_index = feature_layer_fields.index(has_hor_xform_field[0])\n", + " has_xform_status_domain = {'type': 'codedValue',\n", + " 'name': 'esrignss_yesno_domain',\n", + " 'codedValues': [{'name': 'No', 'code': 0},\n", + " {'name': 'Yes', 'code': 1}]}\n", + " feature_layer_fields[has_hor_xform_field_index]['domain'] = has_xform_status_domain\n", + "\n", + " else:\n", + " gnss_metadata_fields['fields'].append({'name': 'esrignss_profile_has_hor_xform',\n", + " 'type': 'esriFieldTypeSmallInteger',\n", + " 'alias': 'Location profile horizontal datum transformation applied',\n", + " 'sqlType': 'sqlTypeOther',\n", + " 'nullable': True,\n", + " 'editable': True,\n", + " 'domain': {'type': 'codedValue',\n", + " 'name': 'esrignss_yesno_domain',\n", + " 'codedValues': [\n", + " {'name': 'No', 'code': 0},\n", + " {'name': 'Yes', 'code': 1}]},\n", + " 'defaultValue': None})\n", + "\n", + " # esrignss_profile_hor_xform\n", + " loc_profile_hor_xform_field = [field for field in feature_layer_fields if field['name'].lower() == 'esrignss_profile_hor_xform']\n", + " \n", + " if not loc_profile_hor_xform_field:\n", + " gnss_metadata_fields['fields'].append({'name': 'esrignss_profile_hor_xform',\n", + " 'type': 'esriFieldTypeString',\n", + " 'alias': 'Location profile horizontal datum transformation',\n", + " 'sqlType': 'sqlTypeOther',\n", + " 'length': 255,\n", + " 'nullable': True,\n", + " 'editable': True,\n", + " 'domain': None,\n", + " 'defaultValue': None})\n", + "\n", + " # esrignss_receiver_geoid\n", + " receiver_geoid_ield = [field for field in feature_layer_fields if field['name'].lower() == 'esrignss_receiver_geoid']\n", + " \n", + " if not receiver_geoid_ield:\n", + " gnss_metadata_fields['fields'].append({'name': 'esrignss_receiver_geoid',\n", + " 'type': 'esriFieldTypeString',\n", + " 'alias': 'Receiver geoid model',\n", + " 'sqlType': 'sqlTypeOther',\n", + " 'length': 60,\n", + " 'nullable': True,\n", + " 'editable': True,\n", + " 'domain': None,\n", + " 'defaultValue': None})\n", + "\n", " # esrignss_avg_h_rms\n", " average_horizontal_accuracy_field = [field for field in feature_layer_fields if\n", " field['name'].lower() == 'esrignss_avg_h_rms']\n", @@ -541,7 +735,52 @@ " 'nullable': True,\n", " 'editable': True,\n", " 'domain': None,\n", - " 'defaultValue': None}) \n" + " 'defaultValue': None}) \n", + "\n", + " # esrignss_h_95_status\n", + " h_95_status_field = [field for field in feature_layer_fields if \n", + " field['name'].lower() == 'esrignss_h_95_status']\n", + "\n", + " if h_95_status_field:\n", + " # Field does exist; check if the domain is set\n", + " if h_95_status_field[0]['domain'] == None:\n", + " if ([operation for operation in operations if operation == 'updateDefinition']):\n", + " operations.append('updateDefinition')\n", + "\n", + " h_95_status_field_index = feature_layer_fields.index(h_95_status_field[0])\n", + " h_95_status_domain = {'type': 'codedValue',\n", + " 'name': 'esrignss_yesno_domain',\n", + " 'codedValues': [{'name': 'No', 'code': 0},\n", + " {'name': 'Yes', 'code': 1}]}\n", + " feature_layer_fields[h_95_status_field_index]['domain'] = h_95_status_domain\n", + "\n", + " else:\n", + " gnss_metadata_fields['fields'].append({'name': 'esrignss_h_95_status',\n", + " 'type': 'esriFieldTypeSmallInteger',\n", + " 'alias': '95% accuracy applied',\n", + " 'sqlType': 'sqlTypeOther',\n", + " 'nullable': True,\n", + " 'editable': True,\n", + " 'domain': {'type': 'codedValue',\n", + " 'name': 'esrignss_yesno_domain',\n", + " 'codedValues': [\n", + " {'name': 'No', 'code': 0},\n", + " {'name': 'Yes', 'code': 1}]},\n", + " 'defaultValue': None})\n", + "\n", + " # esrignss_custom_attributes\n", + " custom_attributes_field = [field for field in feature_layer_fields if field['name'].lower() == 'esrignss_custom_attributes']\n", + " \n", + " if not custom_attributes_field:\n", + " gnss_metadata_fields['fields'].append({'name': 'esrignss_custom_attributes',\n", + " 'type': 'esriFieldTypeString',\n", + " 'alias': 'GNSS custom attributes',\n", + " 'sqlType': 'sqlTypeOther',\n", + " 'length': 2000,\n", + " 'nullable': True,\n", + " 'editable': True,\n", + " 'domain': None,\n", + " 'defaultValue': None})" ] }, { @@ -609,21 +848,6 @@ " 'domain': None,\n", " 'defaultValue': None})\n", "\n", - "\n", - " # esrignss_antenna_height\n", - " antenna_height_field = [field for field in feature_layer_fields if\n", - " field['name'].lower() == 'esrignss_antenna_height']\n", - "\n", - " if not antenna_height_field:\n", - " gnss_metadata_fields['fields'].append({'name': 'esrignss_antenna_height',\n", - " 'type': 'esriFieldTypeDouble',\n", - " 'alias': 'GNSS Antenna height (m)',\n", - " 'sqlType': 'sqlTypeOther',\n", - " 'nullable': True,\n", - " 'editable': True,\n", - " 'domain': None,\n", - " 'defaultValue': None})\n", - "\n", " # esrisnsr_offset_laser_height\n", " laser_height_field = [field for field in feature_layer_fields if\n", " field['name'].lower() == 'esrisnsr_offset_laser_height']\n", @@ -1259,6 +1483,103 @@ " 'defaultValue': None})\n" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Add tilt fields for tilt compensation workflows \n", + "if include_tilt_fields == True and geometry_type == 'esriGeometryPoint':\n", + "\n", + " # esrignss_tilt_compensated\n", + " tilt_compensated_field = [field for field in feature_layer_fields if \n", + " field['name'].lower() == 'esrignss_tilt_compensated']\n", + "\n", + " if tilt_compensated_field:\n", + " # Field does exist; check if the domain is set\n", + " if tilt_compensated_field[0]['domain'] == None:\n", + " if ([operation for operation in operations if operation == 'updateDefinition']):\n", + " operations.append('updateDefinition')\n", + "\n", + " tilt_compensated_field_index = feature_layer_fields.index(tilt_compensated_field[0])\n", + " tilt_compensated_domain = {'type': 'codedValue',\n", + " 'name': 'esrignss_yesno_domain',\n", + " 'codedValues': [{'name': 'No', 'code': 0},\n", + " {'name': 'Yes', 'code': 1}]}\n", + " feature_layer_fields[tilt_compensated_field_index]['domain'] = tilt_compensated_domain\n", + "\n", + " else:\n", + " gnss_metadata_fields['fields'].append({'name': 'esrignss_tilt_compensated',\n", + " 'type': 'esriFieldTypeSmallInteger',\n", + " 'alias': 'Tilt compensated',\n", + " 'sqlType': 'sqlTypeOther',\n", + " 'nullable': True,\n", + " 'editable': True,\n", + " 'domain': {'type': 'codedValue',\n", + " 'name': 'esrignss_yesno_domain',\n", + " 'codedValues': [\n", + " {'name': 'No', 'code': 0},\n", + " {'name': 'Yes', 'code': 1}]},\n", + " 'defaultValue': None})\n", + " \n", + " # esrisnsr_tilt_angle\n", + " tilt_angle_field = [field for field in feature_layer_fields if\n", + " field['name'].lower() == 'esrisnsr_tilt_angle']\n", + "\n", + " if not tilt_angle_field:\n", + " gnss_metadata_fields['fields'].append({'name': 'esrisnsr_tilt_angle',\n", + " 'type': 'esriFieldTypeDouble',\n", + " 'alias': 'Tilt angle (°)',\n", + " 'sqlType': 'sqlTypeOther',\n", + " 'nullable': True,\n", + " 'editable': True,\n", + " 'domain': None,\n", + " 'defaultValue': None})\n", + "\n", + " # esrisnsr_tilt_angle_accuracy\n", + " tilt_angle_accuracy_field = [field for field in feature_layer_fields if\n", + " field['name'].lower() == 'esrisnsr_tilt_angle_accuracy']\n", + "\n", + " if not tilt_angle_accuracy_field:\n", + " gnss_metadata_fields['fields'].append({'name': 'esrisnsr_tilt_angle_accuracy',\n", + " 'type': 'esriFieldTypeDouble',\n", + " 'alias': 'Tilt angle accuracy (°)',\n", + " 'sqlType': 'sqlTypeOther',\n", + " 'nullable': True,\n", + " 'editable': True,\n", + " 'domain': None,\n", + " 'defaultValue': None})\n", + "\n", + " # esrisnsr_tilt_azimuth\n", + " tilt_azimuth_field = [field for field in feature_layer_fields if\n", + " field['name'].lower() == 'esrisnsr_tilt_azimuth']\n", + "\n", + " if not tilt_azimuth_field:\n", + " gnss_metadata_fields['fields'].append({'name': 'esrisnsr_tilt_azimuth',\n", + " 'type': 'esriFieldTypeDouble',\n", + " 'alias': 'Tilt azimuth (°)',\n", + " 'sqlType': 'sqlTypeOther',\n", + " 'nullable': True,\n", + " 'editable': True,\n", + " 'domain': None,\n", + " 'defaultValue': None})\n", + "\n", + " # esrisnsr_tilt_azimuth_accuracy\n", + " tilt_azimuth_accuracy_field = [field for field in feature_layer_fields if\n", + " field['name'].lower() == 'esrisnsr_tilt_azimuth_accuracy']\n", + "\n", + " if not tilt_azimuth_accuracy_field:\n", + " gnss_metadata_fields['fields'].append({'name': 'esrisnsr_tilt_azimuth_accuracy',\n", + " 'type': 'esriFieldTypeDouble',\n", + " 'alias': 'Tilt azimuth accuracy (°)',\n", + " 'sqlType': 'sqlTypeOther',\n", + " 'nullable': True,\n", + " 'editable': True,\n", + " 'domain': None,\n", + " 'defaultValue': None})\n" + ] + }, { "cell_type": "code", "execution_count": null, From 871485b196068ee10b0840113ea6c080b2edc1ab Mon Sep 17 00:00:00 2001 From: Doug Morgenthaler Date: Mon, 22 Jun 2026 19:29:00 -0700 Subject: [PATCH 02/13] Update Pro notebooks and copyright --- README.md | 3 +- notebooks/Add GPS Metadata Fields.ipynb | 1083 +++++++++++++++++++- notebooks/Add GPS Metadata Fields_FS.ipynb | 4 +- 3 files changed, 1033 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index b954daa..67ffbc6 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,6 @@ A set of Python scripts and notebooks to help configure maps and manage data for - [Field Apps Deployment Using Python](notebooks/Field%20Apps%20Deployment%20Using%20Python.ipynb) - [Generate PDF Report](notebooks/Generate%20PDF%20Report/Generate%20PDF%20Report.ipynb) - [Add GPS Metadata Fields (Pro)](notebooks/Add%20GPS%20Metadata%20Fields.ipynb) -- [Add Offset Metadata Fields (Pro)](notebooks/Add%20Offset%20Metadata%20Fields.ipynb) - [Add GPS Metadata Fields](notebooks/Add%20GPS%20Metadata%20Fields_FS.ipynb) - [Configure Search](notebooks/Configure%20Search.ipynb) - [Location Sharing Status](notebooks/Location%20Sharing%20Status.ipynb) @@ -65,7 +64,7 @@ Please see our [guidelines for contributing](https://github.com/esri/contributin ## Licensing -Copyright 2022 Esri +Copyright 2026 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/notebooks/Add GPS Metadata Fields.ipynb b/notebooks/Add GPS Metadata Fields.ipynb index acba159..83a2e59 100644 --- a/notebooks/Add GPS Metadata Fields.ipynb +++ b/notebooks/Add GPS Metadata Fields.ipynb @@ -6,34 +6,37 @@ "source": [ "### Add GPS Metadata fields\n", "\n", - "This notebook is designed for use in ArcGIS Pro 2.9+. See [this topic](https://pro.arcgis.com/en/pro-app/2.8/arcpy/get-started/pro-notebooks.htm) For information on how to use Jupyter notebooks in ArcGIS Pro.\n", + "This notebook is designed for use in ArcGIS Pro 3.2+. See [this topic](https://doc.esri.com/en/arcgis-pro/latest/arcpy/get-started/pro-notebooks.html) For information on how to use Jupyter notebooks in ArcGIS Pro.\n", "\n", - "- Use this script to update an existing line or polygon feature class to support GPS metadata\n", - "- This adds a series of fields, necessary coded value domains, and enables attachments\n", + "- Use this script to update an existing point, line or polygon feature class to support GPS metadata\n", + "- This adds a series of fields, necessary coded value domains, and enables attachments (line and polygon layers only)\n", "\n", "### Steps\n", - "1. Update the `input_feaature_class` variable\n", + "1. Update the `input_feaature_class`, `include_offset`, and `include_tilt` variables\n", "2. Run all cells" ] }, { "cell_type": "code", - "execution_count": 70, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "# update to location of line or polygon feature class\n", - "input_feature_class = r\"C:\\Users\\doug-m\\Documents\\ArcGIS\\Projects\\MyProject\\MyGDB.gdb\\service_lines\"" + "# update to location of point, line or polygon feature class\n", + "input_feature_class = r\"C:\\Users\\doug-m\\Documents\\ArcGIS\\Projects\\MyProject\\MyGDB.gdb\\service_lines\"\n", + "include_offset = False # Set to True if offset GPS metadata fields desired (point layers only)\n", + "include_tilt = False # Set to True if tilt GPS metadata fields desired (point layers only)" ] }, { "cell_type": "code", - "execution_count": 71, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import arcpy\n", "import os\n", + "from dataclasses import field\n", "\n", "def get_geodatabase_path(input_feature_class):\n", " \"\"\"\n", @@ -50,31 +53,73 @@ }, { "cell_type": "code", - "execution_count": 72, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def check_and_create_domains(geodatabase):\n", " \"\"\"\n", - " Checks if the Fix Type domain already exists.\n", + " Checks if the required domains already exists.\n", " If the domains do not exist, they are created\n", " :param geodatabase: (string) the path to the geodatabase to check\n", " :return:\n", " \"\"\"\n", " domains = arcpy.da.ListDomains(geodatabase)\n", " domain_names = [domain.name.lower() for domain in domains]\n", + "\n", + " \n", + " if 'esri_positionsourcetype_domain' in domain_names:\n", + " for domain in domains:\n", + " if domain.name.lower() == 'esri_positionsourcetype_domain':\n", + " # check if cvs 0,1,2,3 4 are in the codedValues\n", + " values = [cv for cv in domain.codedValues]\n", + " if not {0, 1, 2, 3, 4}.issubset(values):\n", + " return \"esri_positionsourcetype_domain is missing a coded value pair.\"\n", + " else:\n", + " # Add the domain and values\n", + " \n", + " arcpy.CreateDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esri_positionsourcetype_domain\",\n", + " domain_description=\"Position Source Type\",\n", + " field_type=\"SHORT\",\n", + " domain_type=\"CODED\",\n", + " split_policy=\"DEFAULT\",\n", + " merge_policy=\"DEFAULT\")\n", + "\n", + " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esri_positionsourcetype_domain\",\n", + " code=\"0\",\n", + " code_description=\"Unknown\")\n", + " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esri_positionsourcetype_domain\",\n", + " code=\"1\",\n", + " code_description=\"User defined\")\n", + " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esri_positionsourcetype_domain\",\n", + " code=\"2\",\n", + " code_description=\"Integrated (System) Location Provider\")\n", + " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esri_positionsourcetype_domain\",\n", + " code=\"3\",\n", + " code_description=\"External GNSS Receiver\")\n", + " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esri_positionsourcetype_domain\",\n", + " code=\"4\",\n", + " code_description=\"Network Location Provider\")\n", + "\n", + " \n", " if 'esri_fix_type_domain' in domain_names:\n", " for domain in domains:\n", " if domain.name.lower() == 'esri_fix_type_domain':\n", " # check if cvs 0,1,2,4,5 are in the codedValues\n", " values = [cv for cv in domain.codedValues]\n", " if not {0, 1, 2, 4, 5}.issubset(values):\n", - " return \"ESRI_FIX_TYPE_DOMAIN is missing a coded value pair.\"\n", + " return \"esri_fix_type_domain is missing a coded value pair.\"\n", " else:\n", " # Add the domain and values\n", " \n", " arcpy.CreateDomain_management(in_workspace=geodatabase,\n", - " domain_name=\"ESRI_FIX_TYPE_DOMAIN\",\n", + " domain_name=\"esri_fix_type_domain\",\n", " domain_description=\"Fix Type\",\n", " field_type=\"SHORT\",\n", " domain_type=\"CODED\",\n", @@ -82,55 +127,162 @@ " merge_policy=\"DEFAULT\")\n", "\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", - " domain_name=\"ESRI_FIX_TYPE_DOMAIN\",\n", + " domain_name=\"esri_fix_type_domain\",\n", " code=\"0\",\n", " code_description=\"Fix not valid\")\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", - " domain_name=\"ESRI_FIX_TYPE_DOMAIN\",\n", + " domain_name=\"esri_fix_type_domain\",\n", " code=\"1\",\n", " code_description=\"GPS\")\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", - " domain_name=\"ESRI_FIX_TYPE_DOMAIN\",\n", + " domain_name=\"esri_fix_type_domain\",\n", " code=\"2\",\n", " code_description=\"Differential GPS\")\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", - " domain_name=\"ESRI_FIX_TYPE_DOMAIN\",\n", + " domain_name=\"esri_fix_type_domain\",\n", " code=\"4\",\n", " code_description=\"RTK Fixed\")\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", - " domain_name=\"ESRI_FIX_TYPE_DOMAIN\",\n", + " domain_name=\"esri_fix_type_domain\",\n", " code=\"5\",\n", - " code_description=\"RTK Float\")" + " code_description=\"RTK Float\")\n", + " \n", + " if 'esrignss_yesno_domain' in domain_names:\n", + " for domain in domains:\n", + " if domain.name.lower() == 'esrignss_yesno_domain':\n", + " # check if cvs 0,1 are in the codedValues\n", + " values = [cv for cv in domain.codedValues]\n", + " if not {0, 1}.issubset(values):\n", + " return \"esrignss_yesno_domain is missing a coded value pair.\"\n", + " else:\n", + " # Add the domain and values\n", + " arcpy.CreateDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esrignss_yesno_domain\",\n", + " domain_description=\" Yes/No\",\n", + " field_type=\"SHORT\",\n", + " domain_type=\"CODED\",\n", + " split_policy=\"DEFAULT\",\n", + " merge_policy=\"DEFAULT\")\n", + "\n", + " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esrignss_yesno_domain\",\n", + " code=\"0\",\n", + " code_description=\"No\")\n", + " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esrignss_yesno_domain\",\n", + " code=\"1\",\n", + " code_description=\"Yes\")\n", + " \n", + " if 'esrignss_correction_source_domain' in domain_names:\n", + " for domain in domains:\n", + " if domain.name.lower() == 'esrignss_correction_source_domain':\n", + " # check if cvs 0,1 are in the codedValues\n", + " values = [cv for cv in domain.codedValues]\n", + " if not {\"Unknown\", \"Direct IP\",\"NTRIP\",\"PPP\",\"Radio\",\"SBAS\"}.issubset(values):\n", + " return \"esrignss_yesno_domain is missing a coded value pair.\"\n", + " else:\n", + " # Add the domain and values\n", + " arcpy.CreateDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esrignss_correction_source_domain\",\n", + " domain_description=\" GNSS Correction Source Type\",\n", + " field_type=\"TEXT\",\n", + " domain_type=\"CODED\",\n", + " split_policy=\"DEFAULT\",\n", + " merge_policy=\"DEFAULT\")\n", + "\n", + " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esrignss_correction_source_domain\",\n", + " code=\"Unknown\",\n", + " code_description=\"Unknown\")\n", + " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esrignss_correction_source_domain\",\n", + " code=\"Direct IP\",\n", + " code_description=\"Direct IP\")\n", + " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esrignss_correction_source_domain\",\n", + " code=\"NTRIP\",\n", + " code_description=\"NTRIP\")\n", + " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esrignss_correction_source_domain\",\n", + " code=\"PPP\",\n", + " code_description=\"PPP\")\n", + " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esrignss_correction_source_domain\",\n", + " code=\"Radio\",\n", + " code_description=\"Radio\")\n", + " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esrignss_correction_source_domain\",\n", + " code=\"SBAS\",\n", + " code_description=\"SBAS\")\n", + " if include_offset:\n", + "\n", + " if 'esri_offset_method_domain' in domain_names:\n", + " for domain in domains:\n", + " if domain.name.lower() == 'esri_offset_method_domain':\n", + " # check if offset methods are in the codedValues\n", + " values = [cv for cv in domain.codedValues]\n", + " if not {'azimuth-azimuth', \n", + " 'distance-azimuth', \n", + " 'distance-distance', \n", + " 'distance-angle', \n", + " 'azimuth-azimuth-backsight', \n", + " 'distance-azimuth-backsight',\n", + " 'distance-distance-backsight',\n", + " 'user-defined'}.issubset(values):\n", + " return \"esri_offset_method_domain is missing a coded value pair.\"\n", + " else:\n", + " # Add the domain and values\n", + " \n", + " arcpy.CreateDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esri_offset_method_domain\",\n", + " domain_description=\"Offset Method Domain\",\n", + " field_type=\"TEXT\",\n", + " domain_type=\"CODED\",\n", + " split_policy=\"DEFAULT\",\n", + " merge_policy=\"DEFAULT\")\n", + "\n", + " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esri_offset_method_domain\",\n", + " code=\"azimuth-azimuth\",\n", + " code_description=\"Azimuth-Azimuth\")\n", + " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esri_offset_method_domain\",\n", + " code=\"distance-angle\",\n", + " code_description=\"Distance-Angle\")\n", + " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esri_offset_method_domain\",\n", + " code=\"distance-azimuth\",\n", + " code_description=\"Distance-Azimuth\")\n", + " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esri_offset_method_domain\",\n", + " code=\"distance-distance\",\n", + " code_description=\"Distance-Distance\")\n", + " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esri_offset_method_domain\",\n", + " code=\"azimuth-azimuth-backsight\",\n", + " code_description=\"Azimuth-Azimuth-Backsight\")\n", + " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esri_offset_method_domain\",\n", + " code=\"distance-azimuth-backsight\",\n", + " code_description=\"Distance-Azimuth-Backsight\")\n", + " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esri_offset_method_domain\",\n", + " code=\"distance-distance-backsight\",\n", + " code_description=\"Distance-Distance-Backsight\")\n", + " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esri_offset_method_domain\",\n", + " code=\"user-defined\",\n", + " code_description=\"User-defined\")\n", + " " ] }, { "cell_type": "code", - "execution_count": 73, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "def add_gnss_fields(feature_class):\n", - " \"\"\"\n", - " This adds specific fields required for GPS units to\n", - " auto-populate in the Field Maps application\n", - " This will report errors if:\n", - " 1) Any of the fields already exist\n", - " 2) The input layer is not a line or polygon layer\n", - " 3) The layer is not found\n", - " 4) The layer is a shapefile\n", - " \"\"\"\n", - "\n", - " if not arcpy.Exists(feature_class):\n", - " return \"Feature layer: {} not found!\".format(feature_class)\n", - " if arcpy.Describe(feature_class).shapeType != \"Polyline\" and arcpy.Describe(feature_class).shapeType != \"Polygon\":\n", - " return \"Feature layer: {} is not a line or polygon layer. Use AddGPSMetadataFields_management instead.\".format(feature_class)\n", - " if arcpy.Describe(feature_class).dataType == \"ShapeFile\":\n", - " return \"ShapeFiles are not supported.\"\n", - "\n", - " # Check the domains to see if they exist and are valid\n", - " # will update if necessary\n", - " geodatabase = get_geodatabase_path(feature_class)\n", - " check_and_create_domains(geodatabase) \n", + "def add_line_poly_gnss_fields(feature_class):\n", "\n", " # Enable Attachments\n", " arcpy.EnableAttachments_management(feature_class)\n", @@ -176,7 +328,6 @@ " field_type=\"SHORT\",\n", " field_alias='Worst Fix Type',\n", " field_is_nullable=\"NULLABLE\",\n", - " field_domain=\"ESRI_FIX_TYPE_DOMAIN\"\n", " )\n", "\n", " if 'esrignss_manual_locations' not in existing_fields:\n", @@ -185,16 +336,844 @@ " field_type=\"LONG\",\n", " field_alias='Number of manual locations',\n", " field_is_nullable=\"NULLABLE\"\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def add_tilt_fields(feature_class):\n", + " \"\"\"\n", + " This adds specific fields required for laser offset workflows\n", + " This will report errors if:\n", + " 1) Any of the fields already exist\n", + " 2) The input layer is not a point layer\n", + " 3) The layer is not found\n", + " 4) The layer is a shapefile\n", + " \"\"\"\n", + "\n", + " if not arcpy.Exists(feature_class):\n", + " return \"Feature layer: {} not found!\".format(feature_class)\n", + " if arcpy.Describe(feature_class).shapeType != \"Point\":\n", + " return \"Feature layer: {} is not a point layer.\".format(feature_class)\n", + " if arcpy.Describe(feature_class).dataType == \"ShapeFile\":\n", + " return \"Shapefiles are not supported.\"\n", + "\n", + " # Check the domains to see if they exist and are valid\n", + " # will update if necessary\n", + " geodatabase = get_geodatabase_path(feature_class)\n", + " check_and_create_domains(geodatabase) \n", + "\n", + " # Add GNSS tilt metadata fields\n", + " existing_fields = [field.name.lower() for field in arcpy.ListFields(feature_class)]\n", + "\n", + " if 'esrignss_tilt_compensated' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_tilt_compensated',\n", + " field_type=\"SHORT\",\n", + " field_alias='Tilt compensated',\n", + " field_is_nullable=\"NULLABLE\"\n", " )\n", "\n", - " # Update GNSS metadata fields with Domains\n", - " domain_fields = [field for field in arcpy.ListFields(feature_class) if field.name == 'esrignss_worst_fixtype']\n", + " if 'esrisnsr_tilt_angle' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrisnsr_tilt_angle',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='Tilt angle (°)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrisnsr_tilt_angle_accuracy' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrisnsr_tilt_angle_accuracy',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='Tilt angle accuracy (°)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrisnsr_tilt_azimuth' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrisnsr_tilt_azimuth',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='Tilt azimuth (°)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrisnsr_tilt_azimuth_accuracy' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrisnsr_tilt_azimuth_accuracy',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='Tilt azimuth accuracy (°)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def add_offset_fields(feature_class):\n", + " \n", + " # Add GNSS metadata fields\n", + " existing_fields = [field.name.lower() for field in arcpy.ListFields(feature_class)]\n", + "\n", + " if 'esrisnsr_offset_method' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrisnsr_offset_method',\n", + " field_type=\"TEXT\",\n", + " field_alias='Offset method',\n", + " field_is_nullable=\"NULLABLE\",\n", + " field_domain=\"esri_offset_method_domain\"\n", + " )\n", + "\n", + " if 'esrisnsr_offset_device' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrisnsr_offset_device',\n", + " field_type=\"TEXT\",\n", + " field_alias='Rangefinder name',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_antenna_height' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_antenna_height',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='GNSS Antenna height (m)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrisnsr_offset_laser_height' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrisnsr_offset_laser_height',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='Rangefinder height (m)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrisnsr_offset_laser_target_ht' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrisnsr_offset_laser_target_ht',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='Laser target height (m)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrisnsr_offset_mag_var' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrisnsr_offset_mag_var',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='Rangefinder Magnetic variation (°)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + " \n", + " if 'esrignss_cp1_latitude' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp1_latitude',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP1 Latitude',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_cp1_longitude' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp1_longitude',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP1 Longitude',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + "\n", + " if 'esrignss_cp1_altitude' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp1_altitude',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP1 Ellipsoidal height (m)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_cp1_h_rms' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp1_h_rms',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP1 Horizontal accuracy (m)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + "\n", + " if 'esrignss_cp1_v_rms' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp1_v_rms',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP1 Vertical accuracy (m)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_cp1_fixdatetime' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp1_fixdatetime',\n", + " field_type=\"DATE\",\n", + " field_alias='CP1 Fix time',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + "\n", + " if 'esrignss_cp1_fixtype' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp1_fixtype',\n", + " field_type=\"SHORT\",\n", + " field_alias='CP1 Fix type',\n", + " field_is_nullable=\"NULLABLE\",\n", + " field_domain=\"esri_fix_type_domain\"\n", + " ) \n", + "\n", + " if 'esrignss_cp1_corr_age' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp1_corr_age',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP1 Correction age',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_cp1_stationid' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp1_stationid',\n", + " field_type=\"SHORT\",\n", + " field_alias='CP1 Station ID',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + "\n", + " if 'esrignss_cp1_numsats' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp1_numsats',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP1 Number of satellites',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_cp1_pdop' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp1_pdop',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP1 PDOP',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + "\n", + " if 'esrignss_cp1_hdop' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp1_hdop',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP1 HDOP',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + " \n", + " if 'esrignss_cp1_vdop' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp1_vdop',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP1 VDOP',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + "\n", + " if 'esrignss_cp1_avg_h_rms' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp1_avg_h_rms',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP1 Average horizontal accuracy (m)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + "\n", + " if 'esrignss_cp1_avg_v_rms' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp1_avg_v_rms',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP1 Average vertical accuracy (m)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + "\n", + " if 'esrignss_cp1_avg_positions' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp1_avg_positions',\n", + " field_type=\"SHORT\",\n", + " field_alias='CP1 Averaged positions',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_cp1_h_stddev' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp1_h_stddev',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP1 Standard deviation (m)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + "\n", + " if 'esrisnsr_cp1_slope_dist' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrisnsr_cp1_slope_dist',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP1 Laser slope distance (m)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + " \n", + " if 'esrisnsr_cp1_inclination' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrisnsr_cp1_inclination',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP1 Laser inclination (°)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + " \n", + " if 'esrisnsr_cp1_azimuth' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrisnsr_cp1_azimuth',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP1 Laser azimuth (°)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + "\n", + " if 'esrignss_cp2_latitude' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp2_latitude',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP2 Latitude',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_cp2_longitude' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp2_longitude',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP2 Longitude',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + "\n", + " if 'esrignss_cp2_altitude' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp2_altitude',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP2 Ellipsoidal height (m)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_cp2_h_rms' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp2_h_rms',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP2 Horizontal accuracy (m)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + "\n", + " if 'esrignss_cp2_v_rms' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp2_v_rms',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP2 Vertical accuracy (m)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_cp2_fixdatetime' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp2_fixdatetime',\n", + " field_type=\"DATE\",\n", + " field_alias='CP2 Fix time',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + "\n", + " if 'esrignss_cp2_fixtype' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp2_fixtype',\n", + " field_type=\"SHORT\",\n", + " field_alias='CP2 Fix type',\n", + " field_is_nullable=\"NULLABLE\",\n", + " field_domain=\"esri_fix_type_domain\"\n", + " ) \n", + "\n", + " if 'esrignss_cp2_corr_age' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp2_corr_age',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP2 Correction age',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_cp2_stationid' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp2_stationid',\n", + " field_type=\"SHORT\",\n", + " field_alias='CP2 Station ID',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + "\n", + " if 'esrignss_cp2_numsats' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp2_numsats',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP2 Number of satellites',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_cp2_pdop' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp2_pdop',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP2 PDOP',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", "\n", + " if 'esrignss_cp2_hdop' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp2_hdop',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP2 HDOP',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + " \n", + " if 'esrignss_cp2_vdop' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp2_vdop',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP2 VDOP',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + "\n", + " if 'esrignss_cp2_avg_h_rms' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp2_avg_h_rms',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP2 Average horizontal accuracy (m)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + "\n", + " if 'esrignss_cp2_avg_v_rms' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp2_avg_v_rms',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP2 Average vertical accuracy (m)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + "\n", + " if 'esrignss_cp2_avg_positions' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp2_avg_positions',\n", + " field_type=\"SHORT\",\n", + " field_alias='CP2 Averaged positions',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_cp2_h_stddev' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_cp2_h_stddev',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP2 Standard deviation (m)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + "\n", + " if 'esrisnsr_cp2_slope_dist' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrisnsr_cp2_slope_dist',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP2 Laser slope distance (m)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + " \n", + " if 'esrisnsr_cp2_inclination' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrisnsr_cp2_inclination',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP2 Laser inclination (°)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + " \n", + " if 'esrisnsr_cp2_azimuth' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrisnsr_cp2_azimuth',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='CP2 Laser azimuth (°)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def add_point_gnss_fields(feature_class):\n", + "\n", + " # Add GNSS metadata fields\n", + " existing_fields = [field.name.lower() for field in arcpy.ListFields(feature_class)]\n", + "\n", + "\n", + " if 'esrignss_receiver' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_receiver',\n", + " field_type=\"DOUBLE\",\n", + " field_length=50,\n", + " field_alias='Receiver name',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_positionsourcetype' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_positionsourcetype',\n", + " field_type=\"SHORT\",\n", + " field_alias='Position source type',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + " \n", + " if 'esrignss_latitude' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_latitude',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='Latitude',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_longitude' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_longitude',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='Longitude',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + " \n", + " if 'esrignss_altitude' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_altitude',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='Ellipsoidal height (m)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_orthometric_height' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_orthometric_height',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='Orthometric height (m)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + " \n", + " if 'esrignss_h_rms' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_h_rms',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='Horizontal accuracy (m)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_v_rms' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_v_rms',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='Vertical accuracy (m)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + " if 'esrignss_fixdatetime' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_fixdatetime',\n", + " field_type=\"DATE\",\n", + " field_alias='Fix time',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_fixtype' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_fixtype',\n", + " field_type=\"SHORT\",\n", + " field_alias='Fix type',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + " \n", + " if 'esrignss_numsats' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_numsats',\n", + " field_type=\"SHORT\",\n", + " field_alias='Number of satellites',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_correction_source_type' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_correction_source_type',\n", + " field_type=\"TEXT\",\n", + " field_length=25,\n", + " field_alias='Correction source type',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + " \n", + " if 'esrignss_correction_source_name' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_correction_source_name',\n", + " field_type=\"TEXT\",\n", + " field_length=100,\n", + " field_alias='Correction source name',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_correctionage' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_correctionage',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='Correction age',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + " \n", + " if 'esrignss_ntrip_mount_point' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_ntrip_mount_point',\n", + " field_type=\"DOUBLE\",\n", + " field_length=100,\n", + " field_alias='Ntrip mount point',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_stationid' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_stationid',\n", + " field_type=\"SHORT\",\n", + " field_alias='Station ID',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + " \n", + " if 'esrignss_pdop' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_pdop',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='PDOP',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + " \n", + " if 'esrignss_hdop' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_hdop',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='HDOP',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + " \n", + " if 'esrignss_vdop' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_vdop',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='VDOP',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + " \n", + " if 'esrignss_direction' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_direction',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='Direction of travel (°)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_speed' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_speed',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='Speed (km/h)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + " \n", + " if 'esrisnsr_azimuth' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrisnsr_azimuth',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='Compass reading (°)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_antenna_height' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_antenna_height',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='GNSS Antenna height (m)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + " \n", + " if 'esrignss_receiver_gcs' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_receiver_gcs',\n", + " field_type=\"TEXT\",\n", + " field_length=60,\n", + " field_alias='Geographic coordinate system',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_receiver_gcs_wkid' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_receiver_gcs_wkid',\n", + " field_type=\"INTEGER\",\n", + " field_alias='Geographic coordinate system WKID',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + " \n", + " if 'esrignss_receiver_ref_epoch' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_receiver_ref_epoch',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='Reference epoch',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_profile_has_hor_xform' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_profile_has_hor_xform',\n", + " field_type=\"SHORT\",\n", + " field_alias='Location profile horizontal datum transformation applied',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + " if 'esrignss_profile_hor_xform' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_profile_hor_xform',\n", + " field_type=\"TEXT\",\n", + " field_length=255,\n", + " field_alias='Location profile horizontal datum transformation',\n", + " field_is_nullable=\"NULLABLE\"\n", + " ) \n", + "\n", + " if 'esrignss_receiver_geoid' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_receiver_geoid',\n", + " field_type=\"TEXT\",\n", + " field_length=60,\n", + " field_alias='Receiver geoid model',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + " if 'esrignss_avg_h_rms' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_avg_h_rms',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='Average horizontal accuracy (m)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + " \n", + " if 'esrignss_avg_v_rms' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_avg_v_rms',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='Average vertical accuracy (m)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_avg_positions' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_avg_positions',\n", + " field_type=\"INTEGER\",\n", + " field_alias='Averaged positions',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + " if 'esrignss_h_stddev' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_h_stddev',\n", + " field_type=\"DOUBLE\",\n", + " field_alias='Standard deviation (m)',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + " \n", + " if 'esrignss_h_95_status' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_h_95_status',\n", + " field_type=\"SHORT\",\n", + " field_alias='95% accuracy applied',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if 'esrignss_custom_attributes' not in existing_fields:\n", + " arcpy.AddField_management(feature_class,\n", + " 'esrignss_custom_attributes',\n", + " field_type=\"TEXT\",\n", + " field_length=100,\n", + " field_alias='GNSS custom attributes',\n", + " field_is_nullable=\"NULLABLE\"\n", + " )\n", + "\n", + " if include_tilt:\n", + " add_tilt_fields(feature_class)\n", + "\n", + " if include_offset:\n", + " add_offset_fields(feature_class)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "def add_gnss_fields(feature_class):\n", + " \"\"\"\n", + " This adds specific fields required for GPS units to\n", + " auto-populate in the Field Maps app\n", + " This will report errors if:\n", + " 1) The layer is not found\n", + " 2) The layer is a shapefile\n", + " 3) The input layer is not a point, line or polygon layer\n", + " \"\"\"\n", + "\n", + " # Make sure we have a Geodatabase feature class\n", + " if not arcpy.Exists(feature_class):\n", + " return \"Feature layer: {} not found!\".format(feature_class)\n", + " if arcpy.Describe(feature_class).dataType == \"ShapeFile\":\n", + " return \"Shapefiles are not supported.\"\n", + "\n", + " shape_type = arcpy.Describe(feature_class).shapeType\n", + " \n", + " match shape_type:\n", + "\n", + " case \"Point\":\n", + " add_point_gnss_fields(feature_class)\n", + " \n", + " case \"Polyline\" | \"Polygon\":\n", + " add_line_poly_gnss_fields(feature_class)\n", + "\n", + " case _:\n", + " return \"Feature layer: {} is not a point, line or polygon layer\".format(feature_class)\n", + "\n", + " # Check the domains to see if they exist and are valid\n", + " # will update if necessary\n", + " geodatabase = get_geodatabase_path(feature_class)\n", + " check_and_create_domains(geodatabase) \n", + "\n", + " domain_fields = [field for field in arcpy.ListFields(feature_class)]\n", + "\n", + " # Update GNSS metadata fields with Domains\n", " for field in domain_fields:\n", + "\n", + " if field.name == 'esrignss_positionsourcetype' and not field.domain:\n", + " arcpy.AssignDomainToField_management(feature_class, field.name, 'esri_positionsourcetype_domain')\n", + "\n", + " if field.name == 'esrignss_fixtype' and not field.domain:\n", + " arcpy.AssignDomainToField_management(feature_class, field.name, 'esri_fix_type_domain')\n", + " \n", + " if field.name == 'esrignss_profile_has_hor_xform' and not field.domain:\n", + " arcpy.AssignDomainToField_management(feature_class, field.name, 'esrignss_yesno_domain')\n", + " \n", + " if field.name == 'esrignss_h_95_status' and not field.domain:\n", + " arcpy.AssignDomainToField_management(feature_class, field.name, 'esrignss_yesno_domain')\n", + "\n", " if field.name == 'esrignss_worst_fixtype' and not field.domain:\n", - " arcpy.AssignDomainToField_management(feature_class, field, 'ESRI_FIX_TYPE_DOMAIN')\n", + " arcpy.AssignDomainToField_management(feature_class, field.name, 'esri_fix_type_domain')\n", + "\n", + " if include_offset:\n", + " if field.name == 'esrisnsr_offset_method' and not field.domain:\n", + " arcpy.AssignDomainToField_management(feature_class, field.name, 'esri_offset_method_domain')\n", + "\n", + " if field.name == 'esrignss_cp1_fixtype' and not field.domain:\n", + " arcpy.AssignDomainToField_management(feature_class, field.name, 'esri_fix_type_domain')\n", "\n", - " return \"Successfully added offset metadata fields and domains.\"" + " if field.name == 'esrignss_cp2_fixtype' and not field.domain:\n", + " arcpy.AssignDomainToField_management(feature_class, field.name, 'esri_fix_type_domain')\n", + "\n", + " if include_tilt: \n", + " if field.name == 'esrignss_tilt_compensated' and not field.domain:\n", + " arcpy.AssignDomainToField_management(feature_class, field.name, 'esrignss_yesno_domain')\n", + "\n", + " return \"Successfully added domains and associated with metadata fields.\"" ] }, { @@ -208,20 +1187,18 @@ } ], "metadata": { - "interpreter": { - "hash": "2f7d5e7f44707441fdf59f9ea9e91257aa419b0f47527e9654c7357783801722" - }, "kernelspec": { - "display_name": "ArcGISPro", - "language": "Python", + "display_name": "arcgis-env", + "language": "python", "name": "python3" }, "language_info": { "file_extension": ".py", + "mimetype": "text/x-python", "name": "python", - "version": "3.7.13" + "version": "3.12.3" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/notebooks/Add GPS Metadata Fields_FS.ipynb b/notebooks/Add GPS Metadata Fields_FS.ipynb index b4ce66a..78f6fef 100644 --- a/notebooks/Add GPS Metadata Fields_FS.ipynb +++ b/notebooks/Add GPS Metadata Fields_FS.ipynb @@ -790,7 +790,7 @@ "outputs": [], "source": [ "# Add metadata fields for laser offset workflows \n", - "if include_offset_fields == True and geometry_type == 'esriGeometryPoint':\n", + "if include_offset_fields and geometry_type == 'esriGeometryPoint':\n", "\n", "\n", " # esrisnsr_offset_method\n", @@ -1490,7 +1490,7 @@ "outputs": [], "source": [ "# Add tilt fields for tilt compensation workflows \n", - "if include_tilt_fields == True and geometry_type == 'esriGeometryPoint':\n", + "if include_tilt_fields and geometry_type == 'esriGeometryPoint':\n", "\n", " # esrignss_tilt_compensated\n", " tilt_compensated_field = [field for field in feature_layer_fields if \n", From 0a22524f1beeec1509c034639b76cf81cfb2379e Mon Sep 17 00:00:00 2001 From: Doug Morgenthaler Date: Mon, 22 Jun 2026 20:46:12 -0700 Subject: [PATCH 03/13] int -> small int data type changes, minor fixes --- notebooks/Add GPS Metadata Fields.ipynb | 8 +++-- notebooks/Add GPS Metadata Fields_FS.ipynb | 39 +++++++++++++--------- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/notebooks/Add GPS Metadata Fields.ipynb b/notebooks/Add GPS Metadata Fields.ipynb index 83a2e59..2464e5c 100644 --- a/notebooks/Add GPS Metadata Fields.ipynb +++ b/notebooks/Add GPS Metadata Fields.ipynb @@ -71,9 +71,9 @@ " if 'esri_positionsourcetype_domain' in domain_names:\n", " for domain in domains:\n", " if domain.name.lower() == 'esri_positionsourcetype_domain':\n", - " # check if cvs 0,1,2,3 4 are in the codedValues\n", + " # check if cvs 0,1,2,3,4,5 are in the codedValues\n", " values = [cv for cv in domain.codedValues]\n", - " if not {0, 1, 2, 3, 4}.issubset(values):\n", + " if not {0, 1, 2, 3, 4, 5}.issubset(values):\n", " return \"esri_positionsourcetype_domain is missing a coded value pair.\"\n", " else:\n", " # Add the domain and values\n", @@ -106,6 +106,10 @@ " domain_name=\"esri_positionsourcetype_domain\",\n", " code=\"4\",\n", " code_description=\"Network Location Provider\")\n", + " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", + " domain_name=\"esri_positionsourcetype_domain\",\n", + " code=\"5\",\n", + " code_description=\"Snapped\")\n", "\n", " \n", " if 'esri_fix_type_domain' in domain_names:\n", diff --git a/notebooks/Add GPS Metadata Fields_FS.ipynb b/notebooks/Add GPS Metadata Fields_FS.ipynb index 78f6fef..8e10ec9 100644 --- a/notebooks/Add GPS Metadata Fields_FS.ipynb +++ b/notebooks/Add GPS Metadata Fields_FS.ipynb @@ -289,7 +289,7 @@ " if not altitude_field:\n", " gnss_metadata_fields['fields'].append({'name': 'esrignss_altitude',\n", " 'type': 'esriFieldTypeDouble',\n", - " 'alias': 'Altitude',\n", + " 'alias': 'Ellipsoidal height (m)',\n", " 'sqlType': 'sqlTypeOther',\n", " 'nullable': True,\n", " 'editable': True,\n", @@ -369,7 +369,7 @@ "\n", " else:\n", " gnss_metadata_fields['fields'].append({'name': 'esrignss_fixtype',\n", - " 'type': 'esriFieldTypeInteger',\n", + " 'type': 'esriFieldTypeSmallInteger',\n", " 'alias': 'Fix type',\n", " 'sqlType': 'sqlTypeOther',\n", " 'nullable': True,\n", @@ -389,7 +389,7 @@ "\n", " if not num_sats_field: \n", " gnss_metadata_fields['fields'].append({'name': 'esrignss_numsats',\n", - " 'type': 'esriFieldTypeInteger',\n", + " 'type': 'esriFieldTypeSmallInteger',\n", " 'alias': 'Number of satellites',\n", " 'sqlType': 'sqlTypeOther',\n", " 'nullable': True,\n", @@ -427,7 +427,7 @@ " 'nullable': True,\n", " 'editable': True,\n", " 'domain': {'type': 'codedValue',\n", - " 'name': 'esrignss_yesno_domain',\n", + " 'name': 'esrignss_correction_source_domain',\n", " 'codedValues': [{'name': 'Unknown', 'code': 'Unknown'},\n", " {'name': 'Direct IP', 'code': 'Direct IP'},\n", " {'name': 'NTRIP', 'code': 'NTRIP'},\n", @@ -469,7 +469,7 @@ " if not ntrip_mountpoint_field:\n", " gnss_metadata_fields['fields'].append({'name': 'esrignss_ntrip_mount_point',\n", " 'type': 'esriFieldTypeString',\n", - " 'alias': 'Ntrip mount point',\n", + " 'alias': 'NTRIP mount point',\n", " 'sqlType': 'sqlTypeOther',\n", " 'length': 100,\n", " 'nullable': True,\n", @@ -482,7 +482,7 @@ "\n", " if not station_id_field:\n", " gnss_metadata_fields['fields'].append({'name': 'esrignss_stationid',\n", - " 'type': 'esriFieldTypeInteger',\n", + " 'type': 'esriFieldTypeSmallInteger',\n", " 'alias': 'Station ID',\n", " 'sqlType': 'sqlTypeOther',\n", " 'nullable': True,\n", @@ -993,7 +993,7 @@ "\n", " else:\n", " gnss_metadata_fields['fields'].append({'name': 'esrignss_cp1_fixtype',\n", - " 'type': 'esriFieldTypeInteger',\n", + " 'type': 'esriFieldTypeSmallInteger',\n", " 'alias': 'CP1 Fix type',\n", " 'sqlType': 'sqlTypeOther',\n", " 'nullable': True,\n", @@ -1026,7 +1026,7 @@ "\n", " if not station_id_field:\n", " gnss_metadata_fields['fields'].append({'name': 'esrignss_cp1_stationid',\n", - " 'type': 'esriFieldTypeInteger',\n", + " 'type': 'esriFieldTypeSmallInteger',\n", " 'alias': 'CP1 Station ID',\n", " 'sqlType': 'sqlTypeOther',\n", " 'nullable': True,\n", @@ -1039,7 +1039,7 @@ "\n", " if not cp1_num_sats_field: \n", " gnss_metadata_fields['fields'].append({'name': 'esrignss_cp1_numsats',\n", - " 'type': 'esriFieldTypeInteger',\n", + " 'type': 'esriFieldTypeSmallInteger',\n", " 'alias': 'CP1 Number of satellites',\n", " 'sqlType': 'sqlTypeOther',\n", " 'nullable': True,\n", @@ -1289,7 +1289,7 @@ "\n", " else:\n", " gnss_metadata_fields['fields'].append({'name': 'esrignss_cp2_fixtype',\n", - " 'type': 'esriFieldTypeInteger',\n", + " 'type': 'esriFieldTypeSmallInteger',\n", " 'alias': 'CP2 Fix type',\n", " 'sqlType': 'sqlTypeOther',\n", " 'nullable': True,\n", @@ -1322,7 +1322,7 @@ "\n", " if not cp2_station_id_field:\n", " gnss_metadata_fields['fields'].append({'name': 'esrignss_cp2_stationid',\n", - " 'type': 'esriFieldTypeInteger',\n", + " 'type': 'esriFieldTypeSmallInteger',\n", " 'alias': 'CP2 Station ID',\n", " 'sqlType': 'sqlTypeOther',\n", " 'nullable': True,\n", @@ -1335,7 +1335,7 @@ "\n", " if not cp2_num_sats_field: \n", " gnss_metadata_fields['fields'].append({'name': 'esrignss_cp2_numsats',\n", - " 'type': 'esriFieldTypeInteger',\n", + " 'type': 'esriFieldTypeSmallInteger',\n", " 'alias': 'CP2 Number of satellites',\n", " 'sqlType': 'sqlTypeOther',\n", " 'nullable': True,\n", @@ -1485,7 +1485,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -1582,9 +1582,18 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Successfully added GPS metadata fields.\n", + "Service definition updated successfully.\n" + ] + } + ], "source": [ "# Check if AddToDefinition operation needs to be added.\n", "initial_featurelayer_fields_count = len(feature_layer_fields)\n", From 2ff2b6cf89ff8e5f1339a1a461768e07c7a348b4 Mon Sep 17 00:00:00 2001 From: Doug Morgenthaler Date: Mon, 22 Jun 2026 22:27:13 -0700 Subject: [PATCH 04/13] PR feedback --- notebooks/Add GPS Metadata Fields.ipynb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/notebooks/Add GPS Metadata Fields.ipynb b/notebooks/Add GPS Metadata Fields.ipynb index 2464e5c..75afa4d 100644 --- a/notebooks/Add GPS Metadata Fields.ipynb +++ b/notebooks/Add GPS Metadata Fields.ipynb @@ -813,7 +813,7 @@ " if 'esrignss_receiver' not in existing_fields:\n", " arcpy.AddField_management(feature_class,\n", " 'esrignss_receiver',\n", - " field_type=\"DOUBLE\",\n", + " field_type=\"TEXT\",\n", " field_length=50,\n", " field_alias='Receiver name',\n", " field_is_nullable=\"NULLABLE\"\n", @@ -927,7 +927,7 @@ " if 'esrignss_ntrip_mount_point' not in existing_fields:\n", " arcpy.AddField_management(feature_class,\n", " 'esrignss_ntrip_mount_point',\n", - " field_type=\"DOUBLE\",\n", + " field_type=\"TEXT\",\n", " field_length=100,\n", " field_alias='Ntrip mount point',\n", " field_is_nullable=\"NULLABLE\"\n", @@ -1089,7 +1089,7 @@ " arcpy.AddField_management(feature_class,\n", " 'esrignss_custom_attributes',\n", " field_type=\"TEXT\",\n", - " field_length=100,\n", + " field_length=2000,\n", " field_alias='GNSS custom attributes',\n", " field_is_nullable=\"NULLABLE\"\n", " )\n", From c108a00b595f4e85e37e9db020f6f5dceae12554 Mon Sep 17 00:00:00 2001 From: Doug Morgenthaler Date: Tue, 23 Jun 2026 10:06:57 -0700 Subject: [PATCH 05/13] Data type and domain updates --- notebooks/Add GPS Metadata Fields.ipynb | 54 ++++++++++++++++--------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/notebooks/Add GPS Metadata Fields.ipynb b/notebooks/Add GPS Metadata Fields.ipynb index 75afa4d..d2ee361 100644 --- a/notebooks/Add GPS Metadata Fields.ipynb +++ b/notebooks/Add GPS Metadata Fields.ipynb @@ -18,19 +18,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 28, "metadata": {}, "outputs": [], "source": [ "# update to location of point, line or polygon feature class\n", - "input_feature_class = r\"C:\\Users\\doug-m\\Documents\\ArcGIS\\Projects\\MyProject\\MyGDB.gdb\\service_lines\"\n", - "include_offset = False # Set to True if offset GPS metadata fields desired (point layers only)\n", - "include_tilt = False # Set to True if tilt GPS metadata fields desired (point layers only)" + "input_feature_class = r\"C:\\Users\\dougm\\Documents\\ArcGIS\\Projects\\MetadataTest\\metadata_test.gdb\\points\"\n", + "include_offset = True # Set to True if offset GPS metadata fields desired (point layers only)\n", + "include_tilt = True # Set to True if tilt GPS metadata fields desired (point layers only)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 29, "metadata": {}, "outputs": [], "source": [ @@ -53,7 +53,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 30, "metadata": {}, "outputs": [], "source": [ @@ -282,7 +282,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 31, "metadata": {}, "outputs": [], "source": [ @@ -345,7 +345,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 32, "metadata": {}, "outputs": [], "source": [ @@ -417,7 +417,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 33, "metadata": {}, "outputs": [], "source": [ @@ -551,7 +551,7 @@ " if 'esrignss_cp1_numsats' not in existing_fields:\n", " arcpy.AddField_management(feature_class,\n", " 'esrignss_cp1_numsats',\n", - " field_type=\"DOUBLE\",\n", + " field_type=\"SHORT\",\n", " field_alias='CP1 Number of satellites',\n", " field_is_nullable=\"NULLABLE\"\n", " )\n", @@ -599,7 +599,7 @@ " if 'esrignss_cp1_avg_positions' not in existing_fields:\n", " arcpy.AddField_management(feature_class,\n", " 'esrignss_cp1_avg_positions',\n", - " field_type=\"SHORT\",\n", + " field_type=\"INTEGER\",\n", " field_alias='CP1 Averaged positions',\n", " field_is_nullable=\"NULLABLE\"\n", " )\n", @@ -712,7 +712,7 @@ " if 'esrignss_cp2_numsats' not in existing_fields:\n", " arcpy.AddField_management(feature_class,\n", " 'esrignss_cp2_numsats',\n", - " field_type=\"DOUBLE\",\n", + " field_type=\"SHORT\",\n", " field_alias='CP2 Number of satellites',\n", " field_is_nullable=\"NULLABLE\"\n", " )\n", @@ -760,7 +760,7 @@ " if 'esrignss_cp2_avg_positions' not in existing_fields:\n", " arcpy.AddField_management(feature_class,\n", " 'esrignss_cp2_avg_positions',\n", - " field_type=\"SHORT\",\n", + " field_type=\"INTEGER\",\n", " field_alias='CP2 Averaged positions',\n", " field_is_nullable=\"NULLABLE\"\n", " )\n", @@ -800,7 +800,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 34, "metadata": {}, "outputs": [], "source": [ @@ -929,7 +929,7 @@ " 'esrignss_ntrip_mount_point',\n", " field_type=\"TEXT\",\n", " field_length=100,\n", - " field_alias='Ntrip mount point',\n", + " field_alias='NTRIP mount point',\n", " field_is_nullable=\"NULLABLE\"\n", " )\n", "\n", @@ -1103,7 +1103,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 35, "metadata": { "scrolled": true }, @@ -1153,6 +1153,9 @@ "\n", " if field.name == 'esrignss_fixtype' and not field.domain:\n", " arcpy.AssignDomainToField_management(feature_class, field.name, 'esri_fix_type_domain')\n", + "\n", + " if field.name == 'esrignss_correction_source_type' and not field.domain:\n", + " arcpy.AssignDomainToField_management(feature_class, field.name, 'esrignss_correction_source_domain')\n", " \n", " if field.name == 'esrignss_profile_has_hor_xform' and not field.domain:\n", " arcpy.AssignDomainToField_management(feature_class, field.name, 'esrignss_yesno_domain')\n", @@ -1182,9 +1185,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 36, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "'Successfully added domains and associated with metadata fields.'" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "add_gnss_fields(input_feature_class)" ] @@ -1192,7 +1206,7 @@ ], "metadata": { "kernelspec": { - "display_name": "arcgis-env", + "display_name": "ArcGISPro", "language": "python", "name": "python3" }, @@ -1200,7 +1214,7 @@ "file_extension": ".py", "mimetype": "text/x-python", "name": "python", - "version": "3.12.3" + "version": "3.13.5" } }, "nbformat": 4, From 0ae2f5a035a39b0a4f847588266e2e3f09e5a161 Mon Sep 17 00:00:00 2001 From: Doug Morgenthaler Date: Tue, 23 Jun 2026 13:52:45 -0700 Subject: [PATCH 06/13] non-functional update --- notebooks/Add GPS Metadata Fields.ipynb | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/notebooks/Add GPS Metadata Fields.ipynb b/notebooks/Add GPS Metadata Fields.ipynb index d2ee361..78aed92 100644 --- a/notebooks/Add GPS Metadata Fields.ipynb +++ b/notebooks/Add GPS Metadata Fields.ipynb @@ -18,19 +18,19 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# update to location of point, line or polygon feature class\n", - "input_feature_class = r\"C:\\Users\\dougm\\Documents\\ArcGIS\\Projects\\MetadataTest\\metadata_test.gdb\\points\"\n", - "include_offset = True # Set to True if offset GPS metadata fields desired (point layers only)\n", - "include_tilt = True # Set to True if tilt GPS metadata fields desired (point layers only)" + "input_feature_class = r\"C:\\Users\\your_username\\Documents\\ArcGIS\\Projects\\MyProject\\MyGDB.gdb\\service_lines\"\n", + "include_offset = False # Set to True if offset GPS metadata fields desired (point layers only)\n", + "include_tilt = False # Set to True if tilt GPS metadata fields desired (point layers only)" ] }, { "cell_type": "code", - "execution_count": 29, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -53,7 +53,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -282,7 +282,7 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -345,7 +345,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -417,7 +417,7 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -800,7 +800,7 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1103,7 +1103,7 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": null, "metadata": { "scrolled": true }, @@ -1185,7 +1185,7 @@ }, { "cell_type": "code", - "execution_count": 36, + "execution_count": null, "metadata": {}, "outputs": [ { From 6d0699ba1804d2a8977766c13289dcdf49aeb01a Mon Sep 17 00:00:00 2001 From: Doug Morgenthaler Date: Wed, 24 Jun 2026 07:48:43 -0700 Subject: [PATCH 07/13] minor offset metadata update --- notebooks/Add Offset Metadata Fields.ipynb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/notebooks/Add Offset Metadata Fields.ipynb b/notebooks/Add Offset Metadata Fields.ipynb index 99feb80..451655a 100644 --- a/notebooks/Add Offset Metadata Fields.ipynb +++ b/notebooks/Add Offset Metadata Fields.ipynb @@ -5,10 +5,9 @@ "metadata": {}, "source": [ "### Add Offset Metadata fields\n", + "This notebook is designed for use in ArcGIS Pro 3.2-3.4. See [this topic](https://doc.esri.com/en/arcgis-pro/latest/arcpy/get-started/pro-notebooks.html) For information on how to use Jupyter notebooks in ArcGIS Pro.\n", "\n", - "This notebook is designed for use in ArcGIS Pro 2.9+. See [this topic](https://pro.arcgis.com/en/pro-app/2.8/arcpy/get-started/pro-notebooks.htm) For information on how to use Jupyter notebooks in ArcGIS Pro.\n", - "\n", - "- Prior to running this script you should ensure that the [Add GPS Metadata Fields](https://pro.arcgis.com/en/pro-app/latest/tool-reference/data-management/add-gps-metadata-fields.htm) Geoprocessing tool has been run on the `input_feature_class`. \n", + "- For Pro 3.5+ use the [Add GPS Metadata Fields](https://pro.arcgis.com/en/pro-app/latest/tool-reference/data-management/add-gps-metadata-fields.htm) Geoprocessing tool instead of this notebook.\n", "- Use this script to update an existing point feature class to support offset workflows\n", "- This adds a series of fields and necessary coded value domains\n", "\n", From ffbc9f41a2f6caf8a253b32ff0ae75d48d945cea Mon Sep 17 00:00:00 2001 From: Doug Morgenthaler Date: Tue, 30 Jun 2026 16:13:02 -0700 Subject: [PATCH 08/13] PR feedback --- notebooks/Add GPS Metadata Fields.ipynb | 46 ++++++++-------------- notebooks/Add GPS Metadata Fields_FS.ipynb | 21 +++++----- 2 files changed, 29 insertions(+), 38 deletions(-) diff --git a/notebooks/Add GPS Metadata Fields.ipynb b/notebooks/Add GPS Metadata Fields.ipynb index 78aed92..858416a 100644 --- a/notebooks/Add GPS Metadata Fields.ipynb +++ b/notebooks/Add GPS Metadata Fields.ipynb @@ -12,7 +12,7 @@ "- This adds a series of fields, necessary coded value domains, and enables attachments (line and polygon layers only)\n", "\n", "### Steps\n", - "1. Update the `input_feaature_class`, `include_offset`, and `include_tilt` variables\n", + "1. Update the `input_feature_class`, `include_offset`, and `include_tilt` variables\n", "2. Run all cells" ] }, @@ -36,7 +36,6 @@ "source": [ "import arcpy\n", "import os\n", - "from dataclasses import field\n", "\n", "def get_geodatabase_path(input_feature_class):\n", " \"\"\"\n", @@ -88,27 +87,27 @@ "\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esri_positionsourcetype_domain\",\n", - " code=\"0\",\n", + " code= 0,\n", " code_description=\"Unknown\")\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esri_positionsourcetype_domain\",\n", - " code=\"1\",\n", + " code= 1,\n", " code_description=\"User defined\")\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esri_positionsourcetype_domain\",\n", - " code=\"2\",\n", + " code= 2,\n", " code_description=\"Integrated (System) Location Provider\")\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esri_positionsourcetype_domain\",\n", - " code=\"3\",\n", + " code= 3,\n", " code_description=\"External GNSS Receiver\")\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esri_positionsourcetype_domain\",\n", - " code=\"4\",\n", + " code= 4,\n", " code_description=\"Network Location Provider\")\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esri_positionsourcetype_domain\",\n", - " code=\"5\",\n", + " code= 5,\n", " code_description=\"Snapped\")\n", "\n", " \n", @@ -132,23 +131,23 @@ "\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esri_fix_type_domain\",\n", - " code=\"0\",\n", + " code= 0,\n", " code_description=\"Fix not valid\")\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esri_fix_type_domain\",\n", - " code=\"1\",\n", + " code= 1,\n", " code_description=\"GPS\")\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esri_fix_type_domain\",\n", - " code=\"2\",\n", + " code= 2,\n", " code_description=\"Differential GPS\")\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esri_fix_type_domain\",\n", - " code=\"4\",\n", + " code= 4,\n", " code_description=\"RTK Fixed\")\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esri_fix_type_domain\",\n", - " code=\"5\",\n", + " code= 5,\n", " code_description=\"RTK Float\")\n", " \n", " if 'esrignss_yesno_domain' in domain_names:\n", @@ -170,20 +169,20 @@ "\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esrignss_yesno_domain\",\n", - " code=\"0\",\n", + " code= 0,\n", " code_description=\"No\")\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esrignss_yesno_domain\",\n", - " code=\"1\",\n", + " code= 1,\n", " code_description=\"Yes\")\n", " \n", " if 'esrignss_correction_source_domain' in domain_names:\n", " for domain in domains:\n", " if domain.name.lower() == 'esrignss_correction_source_domain':\n", - " # check if cvs 0,1 are in the codedValues\n", + " # check if cvs \"Unknown\", \"Direct IP\",\"NTRIP\",\"PPP\",\"Radio\",\"SBAS\" are in the codedValues\n", " values = [cv for cv in domain.codedValues]\n", " if not {\"Unknown\", \"Direct IP\",\"NTRIP\",\"PPP\",\"Radio\",\"SBAS\"}.issubset(values):\n", - " return \"esrignss_yesno_domain is missing a coded value pair.\"\n", + " return \"esrignss_correction_source_domain is missing a coded value pair.\"\n", " else:\n", " # Add the domain and values\n", " arcpy.CreateDomain_management(in_workspace=geodatabase,\n", @@ -1187,18 +1186,7 @@ "cell_type": "code", "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'Successfully added domains and associated with metadata fields.'" - ] - }, - "execution_count": 36, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "add_gnss_fields(input_feature_class)" ] diff --git a/notebooks/Add GPS Metadata Fields_FS.ipynb b/notebooks/Add GPS Metadata Fields_FS.ipynb index 8e10ec9..cd4f403 100644 --- a/notebooks/Add GPS Metadata Fields_FS.ipynb +++ b/notebooks/Add GPS Metadata Fields_FS.ipynb @@ -160,7 +160,7 @@ "\n", " if worst_fixtype_field:\n", " # Field does exist check if the domain is set.\n", - " if worst_fixtype_field[0]['domain'] is None:\n", + " if worst_fixtype_field[0]['domain'] is None: \n", " #if ([operation for operation in operations if operation == 'updateDefinition']):\n", " operations.append('updateDefinition')\n", "\n", @@ -409,7 +409,7 @@ "\n", " corr_source_type_field_index = feature_layer_fields.index(correction_source_type_field[0])\n", " corr_source_type_domain = {'type': 'codedValue',\n", - " 'name': 'esrignss_correction_source_type',\n", + " 'name': 'esrignss_correction_source_domain',\n", " 'codedValues': [{'name': 'Unknown', 'code': 'Unknown'},\n", " {'name': 'Direct IP', 'code': 'Direct IP'},\n", " {'name': 'NTRIP', 'code': 'NTRIP'},\n", @@ -804,12 +804,16 @@ "\n", " offset_method_field_index = feature_layer_fields.index(offset_method_field[0])\n", " offset_method_domain = {'type': 'codedValue',\n", - " 'name': 'esri_offset_method_domain',\n", - " 'codedValues': [{'name': 'Fix not valid', 'code': 0},\n", - " {'name': 'GPS', 'code': 1},\n", - " {'name': 'Differential GPS', 'code': 2},\n", - " {'name': 'RTK Fixed', 'code': 4},\n", - " {'name': 'RTK Float', 'code': 5}]}\n", + " 'name': 'esri_offset_method_domain',\n", + " 'codedValues': [\n", + " {'name': 'Azimuth-Azimuth', 'code': 'azimuth-azimuth'}, \n", + " {'name': 'Distance-Angle', 'code': 'distance-angle'},\n", + " {'name': 'Distance-Azimuth', 'code': 'distance-azimuth'},\n", + " {'name': 'Distance-Distance', 'code': 'distance-distance'},\n", + " {'name': 'Azimuth-Azimuth-Backsight', 'code': 'azimuth-azimuth-backsight'},\n", + " {'name': 'Distance-Azimuth-Backsight', 'code': 'distance-azimuth-backsight'},\n", + " {'name': 'Distance-Distance-Backsight', 'code': 'distance-distance-backsight'},\n", + " {'name': 'User-defined', 'code': 'user-defined'}]}\n", " feature_layer_fields[fix_type_field_index]['domain'] = offset_method_domain\n", "\n", " else:\n", @@ -833,7 +837,6 @@ " {'name': 'User-defined', 'code': 'user-defined'}]},\n", " 'defaultValue': None})\n", "\n", - "\n", " # esrisnsr_offset_device\n", " offset_device_field = [field for field in feature_layer_fields if\n", " field['name'].lower() == 'esrisnsr_offset_device']\n", From ed37eea3a6c38567c35f9d74a27638c9b96d9151 Mon Sep 17 00:00:00 2001 From: Doug Morgenthaler Date: Sun, 12 Jul 2026 09:57:32 -0700 Subject: [PATCH 09/13] PR feedback, handle updateDefinition cases --- notebooks/Add GPS Metadata Fields.ipynb | 26 +- notebooks/Add GPS Metadata Fields_FS.ipynb | 302 +++++++++++---------- 2 files changed, 176 insertions(+), 152 deletions(-) diff --git a/notebooks/Add GPS Metadata Fields.ipynb b/notebooks/Add GPS Metadata Fields.ipynb index 858416a..bf248bc 100644 --- a/notebooks/Add GPS Metadata Fields.ipynb +++ b/notebooks/Add GPS Metadata Fields.ipynb @@ -87,27 +87,27 @@ "\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esri_positionsourcetype_domain\",\n", - " code= 0,\n", + " code = 0,\n", " code_description=\"Unknown\")\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esri_positionsourcetype_domain\",\n", - " code= 1,\n", + " code = 1,\n", " code_description=\"User defined\")\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esri_positionsourcetype_domain\",\n", - " code= 2,\n", + " code = 2,\n", " code_description=\"Integrated (System) Location Provider\")\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esri_positionsourcetype_domain\",\n", - " code= 3,\n", + " code = 3,\n", " code_description=\"External GNSS Receiver\")\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esri_positionsourcetype_domain\",\n", - " code= 4,\n", + " code = 4,\n", " code_description=\"Network Location Provider\")\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esri_positionsourcetype_domain\",\n", - " code= 5,\n", + " code = 5,\n", " code_description=\"Snapped\")\n", "\n", " \n", @@ -131,23 +131,23 @@ "\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esri_fix_type_domain\",\n", - " code= 0,\n", + " code = 0,\n", " code_description=\"Fix not valid\")\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esri_fix_type_domain\",\n", - " code= 1,\n", + " code = 1,\n", " code_description=\"GPS\")\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esri_fix_type_domain\",\n", - " code= 2,\n", + " code = 2,\n", " code_description=\"Differential GPS\")\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esri_fix_type_domain\",\n", - " code= 4,\n", + " code = 4,\n", " code_description=\"RTK Fixed\")\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esri_fix_type_domain\",\n", - " code= 5,\n", + " code = 5,\n", " code_description=\"RTK Float\")\n", " \n", " if 'esrignss_yesno_domain' in domain_names:\n", @@ -169,11 +169,11 @@ "\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esrignss_yesno_domain\",\n", - " code= 0,\n", + " code = 0,\n", " code_description=\"No\")\n", " arcpy.AddCodedValueToDomain_management(in_workspace=geodatabase,\n", " domain_name=\"esrignss_yesno_domain\",\n", - " code= 1,\n", + " code = 1,\n", " code_description=\"Yes\")\n", " \n", " if 'esrignss_correction_source_domain' in domain_names:\n", diff --git a/notebooks/Add GPS Metadata Fields_FS.ipynb b/notebooks/Add GPS Metadata Fields_FS.ipynb index cd4f403..fbbd4b9 100644 --- a/notebooks/Add GPS Metadata Fields_FS.ipynb +++ b/notebooks/Add GPS Metadata Fields_FS.ipynb @@ -30,7 +30,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -40,7 +40,7 @@ "# update this information prior to running\n", "org_url = \"https://www.arcgis.com\"\n", "username = \"doug_nitro\"\n", - "item_id = \"7984f1a3089c47eaad07086b19f6fe92\" # item_id of feature layer\n", + "item_id = \"14b58fc793b34175b2fcb075f8812d3e\" # item_id of feature layer\n", "feature_layer_index = 0 #index of layer you want to update\n", "include_offset_fields = False # indicate if you want offset fields added (point feature layers only)\n", "include_tilt_fields = False # indicate if you want tilt fields added (point feature layers only)\n", @@ -50,7 +50,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -66,6 +66,12 @@ "\n", "feature_layer_collection = FeatureLayerCollection.fromitem(item)\n", "\n", + "if feature_layer_collection.properties.get('isView') == True:\n", + " raise TypeError(\"Feature layer is a view. Cannot update fields on a view\")\n", + "\n", + "if feature_layer_collection.properties.get('subtypeField') is not None:\n", + " raise TypeError(\"Feature layer has subtypes. Cannot update fields on a feature layer with subtypes\")\n", + "\n", "feature_layer = feature_layer_collection.layers[feature_layer_index]\n", "\n", "# get the geometry type\n", @@ -83,11 +89,15 @@ " print (\"Enabled attachments\")\n", "\n", "# Extract existing fields from Feature layer service definition\n", - "feature_layer_fields = feature_layer.properties.fields\n", + "#feature_layer_fields = feature_layer.properties.fields\n", + "feature_layer_fields = feature_layer.properties.get(\"fields\", [])\n", "\n", - "# New fields which need to be added\n", + "# Fields which need to be added\n", "gnss_metadata_fields = {'fields': []}\n", "\n", + "# Fields which need to be updated\n", + "gnss_metadata_fields_updated = {'fields': []}\n", + "\n", "# Operations list - Add or Update GNSS Metadata fields.\n", "operations = []" ] @@ -223,21 +233,23 @@ " positionsourcetype_field = [field for field in feature_layer_fields if field['name'].lower() == 'esrignss_positionsourcetype']\n", "\n", " if positionsourcetype_field:\n", - " # Field does exist; check if the domain is set\n", - " if positionsourcetype_field[0]['domain'] is None:\n", - " operations.append('updateDefinition')\n", - "\n", - " positionsourcetype_field_index = feature_layer_fields.index(positionsourcetype_field[0])\n", - " positionsourcetype_domain = {'type': 'codedValue',\n", + " # Field does exist; check if the domain is correct\n", + " \n", + " positionsourcetype_domain = {'type': 'codedValue',\n", " 'name': 'esri_positionsourcetype_domain',\n", - " 'codedValues': [{'name': 'Unknown',\n", - " 'code': 0},\n", + " 'codedValues': [{'name': 'Unknown', 'code': 0},\n", " {'name': 'User defined', 'code': 1},\n", " {'name': 'Integrated (System) Location Provider', 'code': 2},\n", " {'name': 'External GNSS Receiver', 'code': 3},\n", " {'name': 'Network Location Provider', 'code': 4},\n", - " {'name': 'Snapped', 'code': 5}]},\n", - " feature_layer_fields[positionsourcetype_field_index]['domain'] = positionsourcetype_domain\n", + " {'name': 'Snapped', 'code': 5}]}\n", + "\n", + " # Check if the domain exists and if it matches the expected domain codes\n", + " if positionsourcetype_field[0]['domain'] is None or positionsourcetype_field[0]['domain']['codedValues'] != positionsourcetype_domain['codedValues']:\n", + "\n", + " positionsourcetype_field[0]['domain'] = positionsourcetype_domain\n", + "\n", + " gnss_metadata_fields_updated['fields'].append(positionsourcetype_field[0])\n", "\n", " else:\n", " gnss_metadata_fields['fields'].append({'name': 'esrignss_positionsourcetype',\n", @@ -351,21 +363,23 @@ " fix_type_field = [field for field in feature_layer_fields if field['name'].lower() == 'esrignss_fixtype']\n", "\n", " if fix_type_field:\n", - " # Field does exist; check if the domain is set\n", - " if fix_type_field[0]['domain'] == None:\n", - " if ([operation for operation in operations if operation == 'updateDefinition']):\n", - " operations.append('updateDefinition')\n", + " # Field does exist; check if the domain is correct\n", "\n", - " fix_type_field_index = feature_layer_fields.index(fix_type_field[0])\n", - " fix_type_domain = {'type': 'codedValue',\n", - " 'name': 'esri_fix_type_domain',\n", - " 'codedValues': [{'name': 'Fix not valid',\n", - " 'code': 0},\n", - " {'name': 'GPS', 'code': 1},\n", - " {'name': 'Differential GPS', 'code': 2},\n", - " {'name': 'RTK Fixed', 'code': 4},\n", - " {'name': 'RTK Float', 'code': 5}]}\n", - " feature_layer_fields[fix_type_field_index]['domain'] = fix_type_domain\n", + " fix_type_domain = {'type': 'codedValue',\n", + " 'name': 'esri_fix_type_domain',\n", + " 'codedValues': [{'name': 'Fix not valid',\n", + " 'code': 0},\n", + " {'name': 'GPS', 'code': 1},\n", + " {'name': 'Differential GPS', 'code': 2},\n", + " {'name': 'RTK Fixed', 'code': 4},\n", + " {'name': 'RTK Float', 'code': 5}]}\n", + "\n", + " # Check if the domain exists and if it matches the expected domain codes\n", + " if fix_type_field[0]['domain'] is None or fix_type_field[0]['domain']['codedValues'] != fix_type_domain['codedValues']:\n", + "\n", + " fix_type_field[0]['domain'] = fix_type_domain\n", + "\n", + " gnss_metadata_fields_updated['fields'].append(fix_type_field[0])\n", "\n", " else:\n", " gnss_metadata_fields['fields'].append({'name': 'esrignss_fixtype',\n", @@ -402,21 +416,23 @@ " field['name'].lower() == 'esrignss_correction_source_type']\n", "\n", " if correction_source_type_field:\n", - " # Field does exist; check if the domain is set\n", - " if correction_source_type_field[0]['domain'] == None:\n", - " if ([operation for operation in operations if operation == 'updateDefinition']):\n", - " operations.append('updateDefinition')\n", - "\n", - " corr_source_type_field_index = feature_layer_fields.index(correction_source_type_field[0])\n", - " corr_source_type_domain = {'type': 'codedValue',\n", - " 'name': 'esrignss_correction_source_domain',\n", - " 'codedValues': [{'name': 'Unknown', 'code': 'Unknown'},\n", - " {'name': 'Direct IP', 'code': 'Direct IP'},\n", - " {'name': 'NTRIP', 'code': 'NTRIP'},\n", - " {'name': 'PPP', 'code': 'PPP'},\n", - " {'name': 'Radio', 'code': 'Radio'},\n", - " {'name': 'SBAS', 'code': 'SBAS'}]}\n", - " feature_layer_fields[corr_source_type_field_index]['domain'] = corr_source_type_domain\n", + " # Field does exist; check if the domain is correct\n", + "\n", + " corr_source_type_domain = {'type': 'codedValue',\n", + " 'name': 'esrignss_correction_source_domain',\n", + " 'codedValues': [{'name': 'Unknown', 'code': 'Unknown'},\n", + " {'name': 'Direct IP', 'code': 'Direct IP'},\n", + " {'name': 'NTRIP', 'code': 'NTRIP'},\n", + " {'name': 'PPP', 'code': 'PPP'},\n", + " {'name': 'Radio', 'code': 'Radio'},\n", + " {'name': 'SBAS', 'code': 'SBAS'}]}\n", + "\n", + " # Check if the domain exists and if it matches the expected domain codes\n", + " if correction_source_type_field[0]['domain'] is None or correction_source_type_field[0]['domain']['codedValues'] != corr_source_type_domain['codedValues']:\n", + "\n", + " correction_source_type_field[0]['domain'] = corr_source_type_domain\n", + "\n", + " gnss_metadata_fields_updated['fields'].append(correction_source_type_field[0])\n", "\n", " else:\n", " gnss_metadata_fields['fields'].append({'name': 'esrignss_correction_source_type',\n", @@ -627,17 +643,20 @@ " field['name'].lower() == 'esrignss_profile_has_hor_xform']\n", "\n", " if has_hor_xform_field:\n", - " # Field does exist; check if the domain is set\n", - " if has_hor_xform_field[0]['domain'] == None:\n", - " if ([operation for operation in operations if operation == 'updateDefinition']):\n", - " operations.append('updateDefinition')\n", + " # Field does exist; check if the domain is correct\n", + "\n", + " has_xform_status_domain = {'type': 'codedValue',\n", + " 'name': 'esrignss_yesno_domain',\n", + " 'codedValues': [{'name': 'No', 'code': 0},\n", + " {'name': 'Yes', 'code': 1}]}\n", + " \n", + " # Check if the domain exists and if it matches the expected domain codes\n", + " if has_hor_xform_field[0]['domain'] is None or has_hor_xform_field[0]['domain']['codedValues'] != has_xform_status_domain['codedValues']:\n", + " operations.append('updateDefinition')\n", "\n", - " has_hor_xform_field_index = feature_layer_fields.index(has_hor_xform_field[0])\n", - " has_xform_status_domain = {'type': 'codedValue',\n", - " 'name': 'esrignss_yesno_domain',\n", - " 'codedValues': [{'name': 'No', 'code': 0},\n", - " {'name': 'Yes', 'code': 1}]}\n", - " feature_layer_fields[has_hor_xform_field_index]['domain'] = has_xform_status_domain\n", + " has_hor_xform_field[0]['domain'] = has_xform_status_domain\n", + "\n", + " gnss_metadata_fields_updated['fields'].append(has_hor_xform_field[0])\n", "\n", " else:\n", " gnss_metadata_fields['fields'].append({'name': 'esrignss_profile_has_hor_xform',\n", @@ -742,17 +761,19 @@ " field['name'].lower() == 'esrignss_h_95_status']\n", "\n", " if h_95_status_field:\n", - " # Field does exist; check if the domain is set\n", - " if h_95_status_field[0]['domain'] == None:\n", - " if ([operation for operation in operations if operation == 'updateDefinition']):\n", - " operations.append('updateDefinition')\n", + " # Field does exist; check if the domain is correct\n", + "\n", + " h_95_status_domain = {'type': 'codedValue',\n", + " 'name': 'esrignss_yesno_domain',\n", + " 'codedValues': [{'name': 'No', 'code': 0},\n", + " {'name': 'Yes', 'code': 1}]}\n", + "\n", + " # Check if the domain exists and if it matches the expected domain codes\n", + " if h_95_status_field[0]['domain'] is None or h_95_status_field[0]['domain']['codedValues'] != h_95_status_domain['codedValues']:\n", "\n", - " h_95_status_field_index = feature_layer_fields.index(h_95_status_field[0])\n", - " h_95_status_domain = {'type': 'codedValue',\n", - " 'name': 'esrignss_yesno_domain',\n", - " 'codedValues': [{'name': 'No', 'code': 0},\n", - " {'name': 'Yes', 'code': 1}]}\n", - " feature_layer_fields[h_95_status_field_index]['domain'] = h_95_status_domain\n", + " h_95_status_field[0]['domain'] = h_95_status_domain\n", + "\n", + " gnss_metadata_fields_updated['fields'].append(h_95_status_field[0])\n", "\n", " else:\n", " gnss_metadata_fields['fields'].append({'name': 'esrignss_h_95_status',\n", @@ -797,24 +818,27 @@ " offset_method_field = [field for field in feature_layer_fields if field['name'].lower() == 'esrisnsr_offset_method']\n", "\n", " if offset_method_field:\n", - " # Field does exist; check if the domain is set\n", - " if offset_method_field[0]['domain'] == None:\n", - " if ([operation for operation in operations if operation == 'updateDefinition']):\n", - " operations.append('updateDefinition')\n", - "\n", - " offset_method_field_index = feature_layer_fields.index(offset_method_field[0])\n", - " offset_method_domain = {'type': 'codedValue',\n", - " 'name': 'esri_offset_method_domain',\n", - " 'codedValues': [\n", - " {'name': 'Azimuth-Azimuth', 'code': 'azimuth-azimuth'}, \n", - " {'name': 'Distance-Angle', 'code': 'distance-angle'},\n", - " {'name': 'Distance-Azimuth', 'code': 'distance-azimuth'},\n", - " {'name': 'Distance-Distance', 'code': 'distance-distance'},\n", - " {'name': 'Azimuth-Azimuth-Backsight', 'code': 'azimuth-azimuth-backsight'},\n", - " {'name': 'Distance-Azimuth-Backsight', 'code': 'distance-azimuth-backsight'},\n", - " {'name': 'Distance-Distance-Backsight', 'code': 'distance-distance-backsight'},\n", - " {'name': 'User-defined', 'code': 'user-defined'}]}\n", - " feature_layer_fields[fix_type_field_index]['domain'] = offset_method_domain\n", + " # Field does exist; check if the domain is correct\n", + "\n", + " offset_method_domain = {'type': 'codedValue',\n", + " 'name': 'esri_offset_method_domain',\n", + " 'codedValues': [\n", + " {'name': 'Azimuth-Azimuth', 'code': 'azimuth-azimuth'}, \n", + " {'name': 'Distance-Angle', 'code': 'distance-angle'},\n", + " {'name': 'Distance-Azimuth', 'code': 'distance-azimuth'},\n", + " {'name': 'Distance-Distance', 'code': 'distance-distance'},\n", + " {'name': 'Azimuth-Azimuth-Backsight', 'code': 'azimuth-azimuth-backsight'},\n", + " {'name': 'Distance-Azimuth-Backsight', 'code': 'distance-azimuth-backsight'},\n", + " {'name': 'Distance-Distance-Backsight', 'code': 'distance-distance-backsight'},\n", + " {'name': 'User-defined', 'code': 'user-defined'}]}\n", + " \n", + " # Check if the domain exists and if it matches the expected domain codes\n", + " if offset_method_field[0]['domain'] is None or offset_method_field[0]['domain']['codedValues'] != offset_method_domain['codedValues']:\n", + " operations.append('updateDefinition')\n", + "\n", + " offset_method_field[0]['domain'] = offset_method_domain\n", + "\n", + " gnss_metadata_fields_updated['fields'].append(offset_method_field[0])\n", "\n", " else:\n", " gnss_metadata_fields['fields'].append({'name': 'esrisnsr_offset_method',\n", @@ -979,21 +1003,24 @@ "\n", " if cp1_fix_type_field:\n", " # Field does exist; check if the domain is set\n", - " if fix_type_field[0]['domain'] == None:\n", - " if ([operation for operation in operations if operation == 'updateDefinition']):\n", - " operations.append('updateDefinition')\n", "\n", - " fix_type_field_index = feature_layer_fields.index(fix_type_field[0])\n", - " fix_type_domain = {'type': 'codedValue',\n", - " 'name': 'esri_fix_type_domain',\n", - " 'codedValues': [{'name': 'Fix not valid',\n", - " 'code': 0},\n", - " {'name': 'GPS', 'code': 1},\n", - " {'name': 'Differential GPS', 'code': 2},\n", - " {'name': 'RTK Fixed', 'code': 4},\n", - " {'name': 'RTK Float', 'code': 5}]}\n", - " feature_layer_fields[fix_type_field_index]['domain'] = fix_type_domain\n", + " fix_type_domain = {'type': 'codedValue',\n", + " 'name': 'esri_fix_type_domain',\n", + " 'codedValues': [{'name': 'Fix not valid',\n", + " 'code': 0},\n", + " {'name': 'GPS', 'code': 1},\n", + " {'name': 'Differential GPS', 'code': 2},\n", + " {'name': 'RTK Fixed', 'code': 4},\n", + " {'name': 'RTK Float', 'code': 5}]}\n", + "\n", + " # Check if the domain exists and if it matches the expected domain codes\n", + " if cp1_fix_type_field[0]['domain'] is None or cp1_fix_type_field[0]['domain']['codedValues'] != fix_type_domain['codedValues']:\n", + " operations.append('updateDefinition')\n", + "\n", + " cp1_fix_type_field[0]['domain'] = fix_type_domain\n", "\n", + " gnss_metadata_fields_updated['fields'].append(cp1_fix_type_field[0])\n", + " \n", " else:\n", " gnss_metadata_fields['fields'].append({'name': 'esrignss_cp1_fixtype',\n", " 'type': 'esriFieldTypeSmallInteger',\n", @@ -1274,21 +1301,24 @@ " cp2_fix_type_field = [field for field in feature_layer_fields if field['name'].lower() == 'esrignss_cp2_fixtype']\n", "\n", " if cp2_fix_type_field:\n", - " # Field does exist; check if the domain is set\n", - " if fix_type_field[0]['domain'] == None:\n", - " if ([operation for operation in operations if operation == 'updateDefinition']):\n", - " operations.append('updateDefinition')\n", + " # Field does exist; check if the domain is correct\n", + "\n", + " fix_type_domain = {'type': 'codedValue',\n", + " 'name': 'esri_fix_type_domain',\n", + " 'codedValues': [{'name': 'Fix not valid',\n", + " 'code': 0},\n", + " {'name': 'GPS', 'code': 1},\n", + " {'name': 'Differential GPS', 'code': 2},\n", + " {'name': 'RTK Fixed', 'code': 4},\n", + " {'name': 'RTK Float', 'code': 5}]}\n", + "\n", + " # Check if the domain exists and if it matches the expected domain codes\n", + " if cp2_fix_type_field[0]['domain'] is None or cp2_fix_type_field[0]['domain']['codedValues'] != fix_type_domain['codedValues']:\n", + " operations.append('updateDefinition')\n", "\n", - " fix_type_field_index = feature_layer_fields.index(fix_type_field[0])\n", - " fix_type_domain = {'type': 'codedValue',\n", - " 'name': 'esri_fix_type_domain',\n", - " 'codedValues': [{'name': 'Fix not valid',\n", - " 'code': 0},\n", - " {'name': 'GPS', 'code': 1},\n", - " {'name': 'Differential GPS', 'code': 2},\n", - " {'name': 'RTK Fixed', 'code': 4},\n", - " {'name': 'RTK Float', 'code': 5}]}\n", - " feature_layer_fields[fix_type_field_index]['domain'] = fix_type_domain\n", + " cp2_fix_type_field[0]['domain'] = fix_type_domain\n", + "\n", + " gnss_metadata_fields_updated['fields'].append(cp2_fix_type_field[0])\n", "\n", " else:\n", " gnss_metadata_fields['fields'].append({'name': 'esrignss_cp2_fixtype',\n", @@ -1488,7 +1518,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1500,17 +1530,20 @@ " field['name'].lower() == 'esrignss_tilt_compensated']\n", "\n", " if tilt_compensated_field:\n", - " # Field does exist; check if the domain is set\n", - " if tilt_compensated_field[0]['domain'] == None:\n", - " if ([operation for operation in operations if operation == 'updateDefinition']):\n", - " operations.append('updateDefinition')\n", + " # Field does exist; check if the domain is correct\n", "\n", - " tilt_compensated_field_index = feature_layer_fields.index(tilt_compensated_field[0])\n", - " tilt_compensated_domain = {'type': 'codedValue',\n", - " 'name': 'esrignss_yesno_domain',\n", - " 'codedValues': [{'name': 'No', 'code': 0},\n", - " {'name': 'Yes', 'code': 1}]}\n", - " feature_layer_fields[tilt_compensated_field_index]['domain'] = tilt_compensated_domain\n", + " tilt_compensated_domain = {'type': 'codedValue',\n", + " 'name': 'esrignss_yesno_domain',\n", + " 'codedValues': [{'name': 'No', 'code': 0},\n", + " {'name': 'Yes', 'code': 1}]}\n", + " \n", + " # Check if the domain exists and if it matches the expected domain codes\n", + " if tilt_compensated_field[0]['domain'] is None or tilt_compensated_field[0]['domain']['codedValues'] != tilt_compensated_domain['codedValues']:\n", + " operations.append('updateDefinition')\n", + "\n", + " tilt_compensated_field[0]['domain'] = tilt_compensated_domain\n", + "\n", + " gnss_metadata_fields_updated['fields'].append(tilt_compensated_field[0])\n", "\n", " else:\n", " gnss_metadata_fields['fields'].append({'name': 'esrignss_tilt_compensated',\n", @@ -1585,26 +1618,18 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Successfully added GPS metadata fields.\n", - "Service definition updated successfully.\n" - ] - } - ], + "outputs": [], "source": [ "# Check if AddToDefinition operation needs to be added.\n", - "initial_featurelayer_fields_count = len(feature_layer_fields)\n", - "if (len(gnss_metadata_fields[\n", - " 'fields']) + initial_featurelayer_fields_count\n", - " ) > initial_featurelayer_fields_count:\n", + "if gnss_metadata_fields['fields']:\n", " operations.append('addToDefinition')\n", - " \n", + "\n", + "# Check if UpdateDefinition operation needs to be added.\n", + "if gnss_metadata_fields_updated['fields']: \n", + " operations.append('updateDefinition')\n", + "\n", "# Check if any changes are required\n", "if not operations:\n", " print(\"No changes to GPS metadata fields.\")\n", @@ -1618,10 +1643,9 @@ " gnss_metadata_fields)\n", " print(\"Successfully added GPS metadata fields.\")\n", "\n", - " # Modify\n", + " # Update\n", " else:\n", - " response = feature_layer.manager.update_definition(\n", - " feature_layer_fields)\n", + " response = feature_layer.manager.update_definition(gnss_metadata_fields_updated)\n", " print(\"Successfully updated GPS metadata fields.\")\n", "\n", " result = response['success']\n", From 2a1ebd7e263bd05485ba5da4673f21406d2b0483 Mon Sep 17 00:00:00 2001 From: Doug Morgenthaler Date: Sun, 12 Jul 2026 11:58:35 -0700 Subject: [PATCH 10/13] PR feedback --- notebooks/Add GPS Metadata Fields_FS.ipynb | 76 +++++++++------------- 1 file changed, 32 insertions(+), 44 deletions(-) diff --git a/notebooks/Add GPS Metadata Fields_FS.ipynb b/notebooks/Add GPS Metadata Fields_FS.ipynb index fbbd4b9..dda9676 100644 --- a/notebooks/Add GPS Metadata Fields_FS.ipynb +++ b/notebooks/Add GPS Metadata Fields_FS.ipynb @@ -30,7 +30,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -40,17 +40,17 @@ "# update this information prior to running\n", "org_url = \"https://www.arcgis.com\"\n", "username = \"doug_nitro\"\n", - "item_id = \"14b58fc793b34175b2fcb075f8812d3e\" # item_id of feature layer\n", + "item_id = \"9272c98953db4f5aa580f99e7a529404\" # item_id of feature layer\n", "feature_layer_index = 0 #index of layer you want to update\n", "include_offset_fields = False # indicate if you want offset fields added (point feature layers only)\n", "include_tilt_fields = False # indicate if you want tilt fields added (point feature layers only)\n", "\n", - "gis = GIS(org_url, username)" + "gis = GIS(org_url, username, \"Warden-fern-1\")" ] }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -89,7 +89,6 @@ " print (\"Enabled attachments\")\n", "\n", "# Extract existing fields from Feature layer service definition\n", - "#feature_layer_fields = feature_layer.properties.fields\n", "feature_layer_fields = feature_layer.properties.get(\"fields\", [])\n", "\n", "# Fields which need to be added\n", @@ -169,21 +168,23 @@ " worst_fixtype_field = [field for field in feature_layer_fields if field['name'].lower() == 'esrignss_worst_fixtype']\n", "\n", " if worst_fixtype_field:\n", - " # Field does exist check if the domain is set.\n", - " if worst_fixtype_field[0]['domain'] is None: \n", - " #if ([operation for operation in operations if operation == 'updateDefinition']):\n", + " # Field does exist check if the domain is correct\n", + "\n", + " fixtype_domain = {'type': 'codedValue',\n", + " 'name': 'esri_fix_type_domain',\n", + " 'codedValues': [{'name': 'Fix not valid',\n", + " 'code': 0},\n", + " {'name': 'GPS', 'code': 1},\n", + " {'name': 'Differential GPS', 'code': 2},\n", + " {'name': 'RTK Fixed', 'code': 4},\n", + " {'name': 'RTK Float', 'code': 5}]}\n", + "\n", + " if worst_fixtype_field[0]['domain'] is None or worst_fixtype_field[0]['domain']['codedValues'] != fixtype_domain['codedValues']:\n", " operations.append('updateDefinition')\n", "\n", - " worst_fixtype_field_index = feature_layer_fields.index(worst_fixtype_field[0])\n", - " fixtype_domain = {'type': 'codedValue',\n", - " 'name': 'esri_fix_type_domain',\n", - " 'codedValues': [{'name': 'Fix not valid',\n", - " 'code': 0},\n", - " {'name': 'GPS', 'code': 1},\n", - " {'name': 'Differential GPS', 'code': 2},\n", - " {'name': 'RTK Fixed', 'code': 4},\n", - " {'name': 'RTK Float', 'code': 5}]}\n", - " feature_layer_fields[worst_fixtype_field_index]['domain'] = fixtype_domain\n", + " worst_fixtype_field[0]['domain'] = fixtype_domain\n", + "\n", + " gnss_metadata_fields_updated['fields'].append(worst_fixtype_field[0])\n", "\n", " else:\n", " gnss_metadata_fields['fields'].append({'name': 'esrignss_worst_fixtype',\n", @@ -1622,38 +1623,25 @@ "metadata": {}, "outputs": [], "source": [ - "# Check if AddToDefinition operation needs to be added.\n", - "if gnss_metadata_fields['fields']:\n", - " operations.append('addToDefinition')\n", + "addToDefinition = bool(gnss_metadata_fields[\"fields\"])\n", + "updateDefinition = bool(gnss_metadata_fields_updated[\"fields\"])\n", "\n", - "# Check if UpdateDefinition operation needs to be added.\n", - "if gnss_metadata_fields_updated['fields']: \n", - " operations.append('updateDefinition')\n", - "\n", - "# Check if any changes are required\n", - "if not operations:\n", + "if not (addToDefinition or updateDefinition):\n", " print(\"No changes to GPS metadata fields.\")\n", "else:\n", - " # Add or update service definition\n", - " for operation in operations:\n", - "\n", - " # Add\n", - " if operation == 'addToDefinition':\n", - " response = feature_layer.manager.add_to_definition(\n", - " gnss_metadata_fields)\n", - " print(\"Successfully added GPS metadata fields.\")\n", - "\n", - " # Update\n", + " if addToDefinition:\n", + " response = feature_layer.manager.add_to_definition(gnss_metadata_fields)\n", + " if not response.get(\"success\", False):\n", + " print(\"Failed to add to feature layer service definition.\")\n", " else:\n", - " response = feature_layer.manager.update_definition(gnss_metadata_fields_updated)\n", - " print(\"Successfully updated GPS metadata fields.\")\n", - "\n", - " result = response['success']\n", + " print(\"Successfully added GPS metadata fields.\")\n", "\n", - " if not result:\n", - " print('Failed to update Feature layer service definition.')\n", + " if updateDefinition:\n", + " response = feature_layer.manager.update_definition(gnss_metadata_fields_updated)\n", + " if not response.get(\"success\", False):\n", + " print(\"Failed to update feature layer service definition.\")\n", " else:\n", - " print('Service definition updated successfully.') " + " print(\"Successfully updated GPS metadata fields.\")" ] } ], From eb4723a7f2a17c8d7aed8731e71a8cdf5992d461 Mon Sep 17 00:00:00 2001 From: Doug Morgenthaler Date: Sun, 12 Jul 2026 12:01:16 -0700 Subject: [PATCH 11/13] Missed change --- notebooks/Add GPS Metadata Fields_FS.ipynb | 1 - 1 file changed, 1 deletion(-) diff --git a/notebooks/Add GPS Metadata Fields_FS.ipynb b/notebooks/Add GPS Metadata Fields_FS.ipynb index dda9676..5afc53f 100644 --- a/notebooks/Add GPS Metadata Fields_FS.ipynb +++ b/notebooks/Add GPS Metadata Fields_FS.ipynb @@ -653,7 +653,6 @@ " \n", " # Check if the domain exists and if it matches the expected domain codes\n", " if has_hor_xform_field[0]['domain'] is None or has_hor_xform_field[0]['domain']['codedValues'] != has_xform_status_domain['codedValues']:\n", - " operations.append('updateDefinition')\n", "\n", " has_hor_xform_field[0]['domain'] = has_xform_status_domain\n", "\n", From e2be6031178a2f448b5140bc150bcc164c354dcc Mon Sep 17 00:00:00 2001 From: Doug Morgenthaler Date: Sun, 12 Jul 2026 13:16:14 -0700 Subject: [PATCH 12/13] Update --- notebooks/Add GPS Metadata Fields_FS.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notebooks/Add GPS Metadata Fields_FS.ipynb b/notebooks/Add GPS Metadata Fields_FS.ipynb index 5afc53f..f482b64 100644 --- a/notebooks/Add GPS Metadata Fields_FS.ipynb +++ b/notebooks/Add GPS Metadata Fields_FS.ipynb @@ -45,7 +45,7 @@ "include_offset_fields = False # indicate if you want offset fields added (point feature layers only)\n", "include_tilt_fields = False # indicate if you want tilt fields added (point feature layers only)\n", "\n", - "gis = GIS(org_url, username, \"Warden-fern-1\")" + "gis = GIS(org_url, username)" ] }, { From 399b6bd99fd5aa9629da9abba5c09ff6744e4891 Mon Sep 17 00:00:00 2001 From: Doug Morgenthaler Date: Sun, 12 Jul 2026 13:31:34 -0700 Subject: [PATCH 13/13] remove operations --- notebooks/Add GPS Metadata Fields_FS.ipynb | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/notebooks/Add GPS Metadata Fields_FS.ipynb b/notebooks/Add GPS Metadata Fields_FS.ipynb index f482b64..456539c 100644 --- a/notebooks/Add GPS Metadata Fields_FS.ipynb +++ b/notebooks/Add GPS Metadata Fields_FS.ipynb @@ -39,7 +39,7 @@ "\n", "# update this information prior to running\n", "org_url = \"https://www.arcgis.com\"\n", - "username = \"doug_nitro\"\n", + "username = \"your_username\"\n", "item_id = \"9272c98953db4f5aa580f99e7a529404\" # item_id of feature layer\n", "feature_layer_index = 0 #index of layer you want to update\n", "include_offset_fields = False # indicate if you want offset fields added (point feature layers only)\n", @@ -95,10 +95,7 @@ "gnss_metadata_fields = {'fields': []}\n", "\n", "# Fields which need to be updated\n", - "gnss_metadata_fields_updated = {'fields': []}\n", - "\n", - "# Operations list - Add or Update GNSS Metadata fields.\n", - "operations = []" + "gnss_metadata_fields_updated = {'fields': []}" ] }, { @@ -180,7 +177,6 @@ " {'name': 'RTK Float', 'code': 5}]}\n", "\n", " if worst_fixtype_field[0]['domain'] is None or worst_fixtype_field[0]['domain']['codedValues'] != fixtype_domain['codedValues']:\n", - " operations.append('updateDefinition')\n", "\n", " worst_fixtype_field[0]['domain'] = fixtype_domain\n", "\n", @@ -834,7 +830,6 @@ " \n", " # Check if the domain exists and if it matches the expected domain codes\n", " if offset_method_field[0]['domain'] is None or offset_method_field[0]['domain']['codedValues'] != offset_method_domain['codedValues']:\n", - " operations.append('updateDefinition')\n", "\n", " offset_method_field[0]['domain'] = offset_method_domain\n", "\n", @@ -1015,7 +1010,6 @@ "\n", " # Check if the domain exists and if it matches the expected domain codes\n", " if cp1_fix_type_field[0]['domain'] is None or cp1_fix_type_field[0]['domain']['codedValues'] != fix_type_domain['codedValues']:\n", - " operations.append('updateDefinition')\n", "\n", " cp1_fix_type_field[0]['domain'] = fix_type_domain\n", "\n", @@ -1314,7 +1308,6 @@ "\n", " # Check if the domain exists and if it matches the expected domain codes\n", " if cp2_fix_type_field[0]['domain'] is None or cp2_fix_type_field[0]['domain']['codedValues'] != fix_type_domain['codedValues']:\n", - " operations.append('updateDefinition')\n", "\n", " cp2_fix_type_field[0]['domain'] = fix_type_domain\n", "\n", @@ -1539,7 +1532,6 @@ " \n", " # Check if the domain exists and if it matches the expected domain codes\n", " if tilt_compensated_field[0]['domain'] is None or tilt_compensated_field[0]['domain']['codedValues'] != tilt_compensated_domain['codedValues']:\n", - " operations.append('updateDefinition')\n", "\n", " tilt_compensated_field[0]['domain'] = tilt_compensated_domain\n", "\n",