Perform a feature analysis

Learn how to perform a hot spot feature analysis with the spatial analysis service.

Run a find hot spot analysis on traffic and parking violations in San Francisco.

A feature analysis is the process of using the spatial analysis service to perform server-side geometric and analytic operations on feature data. All feature analysis requests are job requests. The easiest way to programmatically run an analysis request to the spatial analysis service is to use ArcGIS REST JS, which provides a Job class that handles long- running operations.

In this tutorial, you use ArcGIS REST JS to perform a hot spot analysis to find statistically significant clusters of parking violations.

Prerequisites

Steps

Get the starter app

  1. Go to the Display a map tutorial and download the solution.
  2. Unzip the folder and open it in a text editor of your choice, such as Visual Studio Code. The starter app includes the following:
    • callback.html: This contains callback as part of the authentication process.
    • index.html: This contains app logic and the OAuth 2.0 code necessary to perform the authentication.

Set up authentication

Create a new OAuth credential to register the application.

  1. Go to the Create OAuth credentials for user authentication tutorial to create an OAuth credential.
  2. Copy the Client ID and Redirect URL from your OAuth credentials item and paste them to a safe location. They will be used in a later step.

Set developer credentials

  1. In both the index.html and callback.html files, replace YOUR_CLIENT_ID and YOUR_REDIRECT_URL with the client ID and redirect URL of your OAuth credentials.

    index.html
    Use dark colors for code blocks
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
        /* Use for user authentication */
        const session = await arcgisRest.ArcGISIdentityManager.beginOAuth2({
          clientId: "YOUR_CLIENT_ID", // Your client ID from OAuth credentials
          redirectUri: "YOUR_REDIRECT_URL", // The redirect URL registered in your OAuth credentials
          portal: "https://www.arcgis.com/sharing/rest" // Your portal URL
        })
    
    callback.html
    Use dark colors for code blocks
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
        arcgisRest.ArcGISIdentityManager.completeOAuth2({
          clientId: "YOUR_CLIENT_ID", // Your client ID from OAuth credentials
          redirectUri: "YOUR_REDIRECT_URL", // The redirect URL registered in your OAuth credentials
          portal: "https://www.arcgis.com/sharing/rest" // Your portal URL
        })
    
  2. Run the app and ensure you can sign in successfully.

Add script references

In addition to Leaflet and Esri Leaflet, reference the Esri Leaflet renderers plugin to render the analysis results on your map. You also reference the Portal helper class from ArcGIS REST JS to obtain the spatial analysis service URL.

  1. Add references to the renderer plugin and ArcGIS REST JS Portal helper class.

    Use dark colors for code blocks
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
      <!-- ArcGIS REST JS used for user authentication. -->
      <script src="https://unpkg.com/@esri/arcgis-rest-request@4/dist/bundled/request.umd.js"></script>
      <!-- Load Leaflet from CDN -->
      <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" crossorigin="" />
      <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" crossorigin=""></script>
      <!-- Load Esri Leaflet from CDN -->
      <script src="https://unpkg.com/esri-leaflet@3.0.10/dist/esri-leaflet.js"></script>
      <script src="https://unpkg.com/esri-leaflet-vector@4.2.5/dist/esri-leaflet-vector.js"></script>
    
      <!-- Load Esri Leaflet Renderers from CDN -->
      <script src="https://unpkg.com/esri-leaflet-renderers@3.0.1" crossorigin=""></script>
      <!-- ArcGIS REST JS used for spatial analysis URL -->
      <script src="https://unpkg.com/@esri/arcgis-rest-portal@4/dist/bundled/portal.umd.js"></script>
    

Update the map

  1. Update the map's viewpoint to [37.760, -122.445] and a zoom level of 13 to focus in San Fransisco, CA. Then, update the basemap to arcgis/human-geography.

    Use dark colors for code blocks
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
        const map = L.map("map", { minZoom: 2 }).setView([37.760, -122.445], 13);
        const basemapEnum = "arcgis/human-geography";
    
        L.esri.Vector.vectorBasemapLayer(basemapEnum, { token: accessToken }).addTo(map);
    

Display parking violations

To perform feature analysis, you need to provide feature data as input. In this tutorial, you use the SF parking violations hosted feature layer as input data for the hot spot analysis.

  1. Add the parking violation feature layer and the corresponding vector tile layer to the points and pointsVTL variables.

    Expand
    Use dark colors for code blocks
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
        const points =
          "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/sf_traffic_parking_violations_sa_osapi/FeatureServer/0";
    
        const pointsVTL =
          "https://vectortileservices3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/sf_traffic_parking_violations_sa_osapi/VectorTileServer";
    
    
    Expand
  2. To optimize the rendering, add the SF parking violations vector tile layer to the map.

    Expand
    Use dark colors for code blocks
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
        const points =
          "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/sf_traffic_parking_violations_sa_osapi/FeatureServer/0";
    
        const pointsVTL =
          "https://vectortileservices3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/sf_traffic_parking_violations_sa_osapi/VectorTileServer";
    
        map.createPane("vtl");
        map.getPane("vtl").style.zIndex = 800;
    
        const vtlLayer = L.esri.Vector.vectorTileLayer(pointsVTL, {
          pane: "vtl"
        }).addTo(map);
    
    Expand
  3. Run the application. You should see the vector tile layer rendered on the map.

Get the analysis URL

To make a request to the spatial analysis service, you need to get the URL first. The analysis service URL is unique to your organization.

  1. Call the getSelf operation from ArcGIS REST JS to obtain the analysis URL. Pass in accessToken to the authentication property.

    Expand
    Use dark colors for code blocks
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
        const getAnalysisUrl = async (session) => {
          const portalSelf = await arcgisRest.getSelf({
            authentication: session
          });
    
          return portalSelf.helperServices.analysis.url;
        };
    
    Expand

Make the request

Use the Job class and set the operationURL and params required for the selected analysis.

  1. Create a function that submits a Job request to the spatial analysis service using your organization's analysis URL. Set the params required for a hot spot analysis and authenticate using session.

    Expand
    Use dark colors for code blocks
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
        const runAnalysis = async () => {
          const analysisUrl = await getAnalysisUrl(session);
          const operationUrl = `${analysisUrl}/FindHotSpots/submitJob`;
          const params = {
            analysisLayer: { url: points },
            shapeType: "Hexagon",
            outputName: {
              serviceProperties: {
                name: `Leaflet_find_hot_spots_${new Date().getTime()}`
              }
            } //Outputs results as a hosted feature service.
          };
    
          const jobReq = await arcgisRest.Job.submitJob({
            url: operationUrl,
            params: params,
            authentication: session
          });
    
          // get all the results, this will start monitoring and trigger events
          const jobResp = await jobReq.getAllResults();
    
          // jobResp.aggregatedLayer.value.url
          return jobResp;
        };
    
    
    Expand
  2. Create an HTML div element called status and a loader to display the job status.

    Expand
    Use dark colors for code blocks
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
      <div id="status" style="visibility: hidden;">
        <span class="loader"></span>
        <div id="info"></div>
      </div>
    
      <div id="map"></div>
    
    Expand
  3. Apply CSS styling to the status and the loader.

    Use dark colors for code blocks
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
        #status {
          width: 400px;
          background-color: #303336;
          color: #edffff;
          z-index: 1000;
          position: absolute;
          font-family: Arial, Helvetica, sans-serif;
          top: 50%;
          left: 50%;
          transform: translate(-50%, -50%);
          display: flex;
          flex-direction: row;
          justify-content: center;
          padding: 5px;
          border-radius: 5px;
          gap: 10px;
          align-content: center;
          align-items: center;
          margin: auto;
        }
    
        .loader {
          width: 24px;
          height: 24px;
          border: 5px solid #edffff;
          border-bottom-color: #303336;
          border-radius: 50%;
          display: inline-block;
          box-sizing: border-box;
          animation: rotation 2s linear infinite;
        }
    
        @keyframes rotation {
          0% {
            transform: rotate(0deg);
          }
    
          100% {
            transform: rotate(360deg);
          }
        }
    
  4. Create a function called showInfo to control the visibility and content of the status element.

    Expand
    Use dark colors for code blocks
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
        const showInfo = (visible, msg) => {
          const statusUi = document.getElementById("status");
          !visible ? (statusUi.style.visibility = "hidden") : (statusUi.style.visibility = "visible");
          const infoUi = document.getElementById("info");
          infoUi.innerText = msg;
        };
    
        const runAnalysis = async () => {
          const analysisUrl = await getAnalysisUrl(session);
          const operationUrl = `${analysisUrl}/FindHotSpots/submitJob`;
          const params = {
            analysisLayer: { url: points },
            shapeType: "Hexagon",
            outputName: {
              serviceProperties: {
                name: `Leaflet_find_hot_spots_${new Date().getTime()}`
              }
            } //Outputs results as a hosted feature service.
          };
    
          const jobReq = await arcgisRest.Job.submitJob({
            url: operationUrl,
            params: params,
            authentication: session
          });
    
          // get all the results, this will start monitoring and trigger events
          const jobResp = await jobReq.getAllResults();
    
          // jobResp.aggregatedLayer.value.url
          return jobResp;
        };
    
    
    Expand
  5. Use the function to dynamically update the status element with the current status of the analysis.

    Expand
    Use dark colors for code blocks
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
        const runAnalysis = async () => {
          const analysisUrl = await getAnalysisUrl(session);
          const operationUrl = `${analysisUrl}/FindHotSpots/submitJob`;
          const params = {
            analysisLayer: { url: points },
            shapeType: "Hexagon",
            outputName: {
              serviceProperties: {
                name: `Leaflet_find_hot_spots_${new Date().getTime()}`
              }
            } //Outputs results as a hosted feature service.
          };
    
          const jobReq = await arcgisRest.Job.submitJob({
            url: operationUrl,
            params: params,
            authentication: session
          });
    
          showInfo(true, "Initializing analysis...");
    
          // listen to the status event to get updates every time the job status is checked.
          jobReq.on(arcgisRest.JOB_STATUSES.Status, (jobInfo) => {
            showInfo(true, "Hot spot analysis running...");
          });
    
          // get all the results, this will start monitoring and trigger events
          const jobResp = await jobReq.getAllResults();
    
          // jobResp.aggregatedLayer.value.url
          return jobResp;
        };
    
    Expand
  6. Call the runAnalysis function and store its response in jobResponse.

    Expand
    Use dark colors for code blocks
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
        const showInfo = (visible, msg) => {
          const statusUi = document.getElementById("status");
          !visible ? (statusUi.style.visibility = "hidden") : (statusUi.style.visibility = "visible");
          const infoUi = document.getElementById("info");
          infoUi.innerText = msg;
        };
    
        const runAnalysis = async () => {
          const analysisUrl = await getAnalysisUrl(session);
          const operationUrl = `${analysisUrl}/FindHotSpots/submitJob`;
          const params = {
            analysisLayer: { url: points },
            shapeType: "Hexagon",
            outputName: {
              serviceProperties: {
                name: `Leaflet_find_hot_spots_${new Date().getTime()}`
              }
            } //Outputs results as a hosted feature service.
          };
    
          const jobReq = await arcgisRest.Job.submitJob({
            url: operationUrl,
            params: params,
            authentication: session
          });
    
          showInfo(true, "Initializing analysis...");
    
          // listen to the status event to get updates every time the job status is checked.
          jobReq.on(arcgisRest.JOB_STATUSES.Status, (jobInfo) => {
            showInfo(true, "Hot spot analysis running...");
          });
    
          // get all the results, this will start monitoring and trigger events
          const jobResp = await jobReq.getAllResults();
    
          // jobResp.aggregatedLayer.value.url
          return jobResp;
        };
    
        const jobResponse = await runAnalysis()
    
    Expand

Display results

The results of a feature analysis are returned as feature data.

  1. Add the layer to the map by accessing the URL of the resulting hosted feature layer from the job's response. Then, hide the status element.

    Expand
    Use dark colors for code blocks
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
        L.esri.featureLayer({
          url: jobResponse.hotSpotsResultLayer.value.url,
          token: accessToken
        }).addTo(map);
    
        showInfo(false, "");
    
    Expand

Run the app

Run the application and navigate to your localhost, for example https://localhost:8080.

After signing in, a request is sent to the spatial analysis service to perform a hot spot analysis. When the job is complete, the results of the analysis will display on the map. The analysis can take up to a minute to complete.

What's next?

To learn how to perform other types of feature analysis, go to the related tutorials in the Spatial analysis services guide:

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.