Select to view content in your preferred language

Arcade dynamic symbology script for continuity check

586
9
Jump to solution
08-03-2024 11:46 PM
Labels (2)
DominicReed
Occasional Contributor

Hi all, 

I am trying to make a dynamic symbology for a time dependent hosted feature layer. Where I have some point data and its last 15 minutes record (changes in every minute) coming from the geoevent server. This is a weather station data, I would like to turn my map symbol red if there is a rain over 50 mm for the last 15 minutes. I was planning to use arcade, tried the following code: 

 

var rainfallField = $feature.rainfall;

// Check if the rainfall is greater than 50 mm for all records
var allRecordsAboveThreshold = true;
for (var i = 0; i < Count(rainfallField); i++) {
    if (rainfallField[i] <= 50) {
        allRecordsAboveThreshold = false;
        break;
    }
}

// Return a color based on the condition
if (allRecordsAboveThreshold) {
    return "red"; // All records have rainfall > 50 mm
} else {
    return "blue"; // Not all records have rainfall > 50 mm
}

 

 

But it do not give any output. Is it possible to manage it using arcade expressions? 

1 Solution

Accepted Solutions
TanuHoque
Esri Regular Contributor

thanks @DominicReed for answering my questions

here is what I'd do:

  • create a feature class and a table in your enterprise database
    • the feature class is for your weather stations
    • the table is for your time series data
    • of course, you need to have some ID field e.g. weather-station-id in both feature class and table
  • create a by-ref feature service with the time-series table
  • point your geoevent process to feed data to your newly created by-ref feature service
  • in ArcGIS Pro, create a query layer using a SQL using aggregated function and joins e.g.
    • SELECT s.*, r.Total_Rainfall
      FROM RAINFALL_STATIONS s
      INNER JOIN
      (SELECT site_no,
      SUM(rainfall_inch) AS Total_Rainfall
      FROM RAINFALL_TIMESERIES
      GROUP BY site_no) r
      ON s.site_no = r.site_no
  • now you have a layer that shows weather stations with total rainfall for each stations. 
  • you can symbolize feature appropriately
  • share it as a map service (aka map image layer)


this blog might give you a bit more details information about the later half of instructions from above.

https://www.esri.com/arcgis-blog/products/arcgis-pro/mapping/dynamic-spatiotemporal-exploratory-anal... 

 

please let me know if you have any questions

View solution in original post

9 Replies
changhau
Deactivated User

I mean, that's how it should be, right? You shouldn't need to change the schema so much before it's a data product you're hosting, but then again I don't know you're setup and system capabilities. If you're not seeing data (row level) edits in joined views, you're either filtering the changes, or something is wrong. I use these with dynamic, constantly changing datasets, and all is good https://speedtest.vet/ .

jcarlson
MVP Esteemed Contributor

Arcade has this concept called profiles. https://developers.arcgis.com/arcade/profiles/

The short version is that Arcade capabilities are dependent upon the context in which it's used. For symbology, for instance, your expression will only have access to the individual record it's being evaluated for. The expression can't "see" anything outside of a single feature. But the expression will run on every single feature separately. To think of it another way, the expression you write in a symbology expression is already in a for loop.

That in mind, trying to do something "for all records" just won't work. When you do your loop, it's only going to evaluate once, because your rainfallField variable only has a single number in it.

If you just want to color-code based on the value, try:

return Iif(
  $feature.rainfall <= 50,
  'blue',
  'red'
)

And keep in mind that this won't automatically make your symbols red and blue. Nor will it actually give you all possible categories of your expression. If you don't have any features that evaluate to "red", that category won't show up, and you'll have to manually define it.

And you'll still need to go into each category and actually set the color.

- Josh Carlson
Kendall County GIS
DominicReed
Occasional Contributor

Hi @jcarlson,

Thanks for your explanations. I am using this logic for considering other factors for the symbology, as this expression automatically detects the latest value for each stations. Only for rain rate I need to consider this 15 minute issue. That's where I am stuggling actually! 

0 Kudos
TanuHoque
Esri Regular Contributor

@DominicReed 

This looks like an interesting problem. I hope you won't mind if I ask you a few questions:

  1. I see you said it is a hosted feature service. Just to make sure I didn't misunderstand you - it is not a stream service, right? And a geoevent process feeds data into your hosted feature service. Is that correct?
  2. You said it is a point layer and it contains rainfall data for every time for last 15 min. That means there will be max 15 records for each weather station. Did I understand it correctly?
  3. if #2 is true, does it mean that you have 15 overlapped point features for each weather station?
  4. if #3 is also true, just a curiosity question - can it be normalized, and spatial data and time-series data can be stored in separate layer and table respectively?

 

Thanks.

Tanu

 

DominicReed
Occasional Contributor

Hi @TanuHoque , 
Thanks for asking. Yes, I did not use a stream service due to some other analytics and integration with experience builder, and yes, a geoevent process feeds data into my hosted feature service. And spatial data and time-series data can be stored in separate layer and table respectively, however, this layer is specially for creating a symbology, there are other logics, which I have already managed, but struggling with this one. 

0 Kudos
TanuHoque
Esri Regular Contributor

thanks @DominicReed for answering my questions

here is what I'd do:

  • create a feature class and a table in your enterprise database
    • the feature class is for your weather stations
    • the table is for your time series data
    • of course, you need to have some ID field e.g. weather-station-id in both feature class and table
  • create a by-ref feature service with the time-series table
  • point your geoevent process to feed data to your newly created by-ref feature service
  • in ArcGIS Pro, create a query layer using a SQL using aggregated function and joins e.g.
    • SELECT s.*, r.Total_Rainfall
      FROM RAINFALL_STATIONS s
      INNER JOIN
      (SELECT site_no,
      SUM(rainfall_inch) AS Total_Rainfall
      FROM RAINFALL_TIMESERIES
      GROUP BY site_no) r
      ON s.site_no = r.site_no
  • now you have a layer that shows weather stations with total rainfall for each stations. 
  • you can symbolize feature appropriately
  • share it as a map service (aka map image layer)


this blog might give you a bit more details information about the later half of instructions from above.

https://www.esri.com/arcgis-blog/products/arcgis-pro/mapping/dynamic-spatiotemporal-exploratory-anal... 

 

please let me know if you have any questions

DominicReed
Occasional Contributor

Hi @TanuHoque,

Thanks for your solution, although when thinking about your questions, I have discovered a similar way around, but your idea will help me to bypass lots of steps! Thanks a lot again! 

ArchitSrivastava
Frequent Contributor

Hello @DominicReed,

In addition to suggestions of @jcarlson , I would suggest you to try to use "FeatureSetByPortalItem"(for reference) to  achieve the filtering functionality you desire, you might need to structure your Arcade expression a bit differently to create a dictionary that links the data to Hosted Feature service directly. Here's a suggested method, how you can approach it:

  • Create a Dictionary with Codes:
    • You need a dictionary where each specialty is a key, and the value is a list of health unit codes associated with that specialty.
  • Use the Dictionary for Filtering:
    • Use this dictionary to filter the point features based on the selected specialty.

Here's a probable way to  approach using Arcade to achieve this (I have made some assumption in regards to dictionary components, you would need to adjust that accordingly):

 

// Access the portal and feature set
var portal = Portal('https://www.iede.rs.gov.br/portal');
var fs = FeatureSetByPortalItem(portal, "<Item_ID>", <Layer_ID>);

// Initialize a dictionary to store specialties and their corresponding health unit codes
var specialtyDict = {};

// Iterate over the features in the feature set
for (var feature in fs) {
var specialty = feature['DS_ESPECIALIDADE'];
var healthUnitCode = feature['CNES_ref'];

// Check if the specialty already exists in the dictionary
if (!HasKey(specialtyDict, specialty)) {
// If not, initialize an empty array for this specialty
specialtyDict[specialty] = [];
}

// Add the health unit code to the array for this specialty
Push(specialtyDict[specialty], healthUnitCode);
}

// Return the dictionary as a JSON object
return Text(specialtyDict);

 

Description:

  • FeatureSet Access: Access the feature set using `FeatureSetByPortalItem` and the specific table index.
  • Dictionary Initialization: Create an empty dictionary to store specialties as keys and arrays of health unit codes as values.
  • Iterate Over Features: Loop through each feature in the feature set, extracting the specialty and health unit code.
  • Check and Add: Check if the specialty is already a key in the dictionary. If not, add it and initialize an array. Then, push the health unit code into the array.
  • Return the Dictionary: Finally, return the dictionary as a JSON object, which can be used to filter the map points.

Hope it helps!

DominicReed
Occasional Contributor

Hi there, I tried this FeatureSetByPortalItem but the problem is, it is not supported for symbology, it only supports popup and dashboard, as far as I learned from my endeavor! Thanks for your tips! 

0 Kudos