Skip to content

Instantly share code, notes, and snippets.

@Giammaria
Last active February 25, 2025 15:41
Show Gist options
  • Save Giammaria/4d51ccfff408105407672fe979952ffd to your computer and use it in GitHub Desktop.
Save Giammaria/4d51ccfff408105407672fe979952ffd to your computer and use it in GitHub Desktop.
20241219_sf_readiness_gateway_center_viz_v1_v
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"width": 652,
"height": 676,
"autosize": "none",
"background": "transparent",
"signals": [
{"name": "inCognos", "value": true},
{"name": "windowLocationOrigin", "value": ""},
{"name": "initialTimestamp", "init": "now()"},
{"name": "startRendering", "value": true},
{
"name": "width",
"update": "inCognos ? !startRendering ? 0 : containerSize()[0] : width"
},
{
"name": "height",
"update": "inCognos ? !startRendering ? 0 : containerSize()[1] : height"
},
{
"name": "radialWidth",
"update": "min(containerSize()[0], containerSize()[1]*0.925)"
},
{
"name": "radialHeight",
"update": "min(containerSize()[0], containerSize()[1])*0.925"
},
{
"name": "padding",
"update": "0"
},
{"name": "counter", "init": "now()"},
{"name": "horizontalRuleWidthPercent", "value": 0.3},
{"name": "centerRuleVerticalOffset", "update": "0.016*height"},
{"name": "dayInMilliseconds", "value": 86400000},
{
"name": "persistOVLColors",
"init": "showColorIndicatorsConfig.initialValue",
"on": [
{
"events": "@group_showColorIndicatorsToggle:pointerdown",
"update": "!persistOVLColors"
}
]
},
{
"name": "readinessMetric",
"init": "configButtons.initialValue",
"on": [
{
"events": "@readiness_metric_button_background:pointerdown",
"update": "datum.datum.name"
}
]
},
{
"name": "configButtons",
"description": "configurations for the button controls",
"update": "{initialValue: 'cRate', padding: height*0.0054884742, yOffset: (0.0027442371*height), label: {text: 'Readiness Metric', font: 'Segoe UI', fontSize: height*0.0175, fill: mediumColor, fontStyle: 'regular', dy: 0.02*height}, outerStroke: '#777', fill: lightColor, selectedFill: '#b5cae1'}"
},
{
"name": "showColorIndicatorsConfig",
"description": "configurations for the show color indicators toggle control",
"update": "{enabled: true, initialValue: true, xOffset: 0.04390779363*height, track: {height: 0.0082327113*height, width: height*0.02744237102, cornerRadius: 0.0054884742*height, fill: lightColor, stroke: '#777', strokeWidth: 1}, handle: {stroke: '#777', strokeWidth: 1, fill: '#fff'}, label: {text: 'Color Indicators', font: 'Segoe UI', fontSize: 0.01317233809*height, fill: mediumColor, fontStyle: 'regular', dy: height*0.0082327113}, on: {fill: '#b5cae1', fillOpacity: 1, stroke: '#777', strokeWidth: 1}, tooltip: {text: 'Show/hide indicator colors'}}"
},
{
"name": "xAxisOuterPaddingPercentage",
"description": "percentage of padding between x-axis and day text marks",
"value": 0.015
},
{
"name": "lightColor",
"description": "light color for theme as hex value",
"value": "#EEE"
},
{
"name": "semiLightColor",
"description": "semi-light color for theme as hex value",
"value": "#DEDEDE"
},
{
"name": "mediumColor",
"description": "medium color for theme as hex value",
"value": "#AAA"
},
{
"name": "darkColor",
"description": "dark color for theme as hex value",
"value": "#999"
},
{
"name": "backgroundRGB",
"description": "rgb value of the canvas background",
"value": "#000"
},
{
"name": "yearAxisRadius",
"description": "radius for the year axis domain",
"update": "min(radialWidth, radialHeight)/2.2"
},
{
"name": "monthAxisRadius",
"description": "radius for the month axis domain",
"update": "yearAxisRadius-(height*0.02744237102)"
},
{
"name": "dayRadius",
"description": "radius for the day line (text) marks",
"update": "monthAxisRadius-(height*0.00658616904)"
},
{
"name": "outerContentRadius",
"description": "radius for the content marks inside the radial axes",
"update": "dayRadius-(height*0.07)"
},
{
"name": "innerContentRadius",
"description": "radius for the content marks inside the radial axes",
"update": "outerContentRadius/2"
},
{"name": "placementNumberOfRows", "value": 4},
{"name": "fleetPlacementRadialOffset", "init": "PI/20"},
{"name": "fleetIconSize", "update": "0.03*radialHeight"},
{
"name": "hoverMonth",
"description": "datum of the currently focused month",
"init": "{FirstOfMonthDate: extent(pluck(data('dataset_exploded'), 'FirstOfMonthDate'))[1]}",
"on": [
{
"events": {
"type": "mouseover",
"markname": "month_axis_hover_interactive"
},
"update": "datum"
}
]
},
{
"name": "hoverUnit",
"description": "datum of the currently focused unit",
"init": "null",
"on": [
{
"events": {
"type": "mouseover",
"markname": "placement_interactive_arcs"
},
"update": "datum"
},
{
"events": {
"type": "mouseout",
"markname": "placement_interactive_arcs"
},
"update": "null"
}
]
}
],
"marks": [
{
"name": "radial_visual",
"type": "group",
"encode": {
"update": {
"x": {"signal": "startRendering ? width/2-radialWidth/2 : 0"},
"y": {"signal": "startRendering ? height/2-radialHeight*0.5 : 0"}
}
},
"marks": [
{
"name": "background",
"type": "arc",
"encode": {
"update": {
"x": {"signal": "radialWidth/2"},
"y": {"signal": "radialHeight/2"},
"outerRadius": {"signal": "yearAxisRadius"},
"endAngle": {"signal": "2*PI"},
"fill": {"value": "#000"}
}
}
},
{
"name": "day_bars",
"description": "colored pipe (|) text marks that serve as a daily indicator",
"from": {"data": "dataset_exploded"},
"interactive": false,
"type": "text",
"encode": {
"update": {
"x": {"signal": "radialWidth/2"},
"dx": {"signal": "datum.Day === 1 ? -1 : 0"},
"y": {"signal": "radialHeight/2"},
"text": {
"signal": "datum.Day === 1 ? '⯌' : datum.Day === 15 ? '|' : null"
},
"align": {"value": "center"},
"fontfamily": {"value": "consolas"},
"fontSize": {
"signal": "datum.Day === 1 || datum.IsLastDayOfMonth ? 10 : 5"
},
"fontWeight": {"value": 400},
"baseline": {"value": "top"},
"fill": {"signal": "mediumColor"},
"theta": {"scale": "dayAxisScale", "field": "Date"},
"radius": {"signal": "dayRadius"},
"angle": {
"signal": "scale('dayAxisScale', datum['Date'])*(180/PI)"
}
}
}
},
{
"name": "month_axis_domain",
"description": "month axis domain arcs",
"from": {"data": "day_bars"},
"interactive": false,
"transform": [
{
"type": "formula",
"expr": "datum.datum.datum.FirstOfMonthDate",
"as": "FirstOfMonthDate"
},
{
"type": "formula",
"expr": "datum['datum']['theta']",
"as": "theta"
},
{
"type": "joinaggregate",
"fields": ["theta", "theta"],
"ops": ["min", "max"],
"groupby": ["FirstOfMonthDate"],
"as": ["startAngle", "endAngle"]
},
{
"type": "formula",
"expr": "datum['startAngle']+(datum['endAngle']-datum['startAngle'])/2",
"as": "midAngle"
},
{
"type": "formula",
"expr": "datum['midAngle'] < PI/2 || datum['midAngle'] > PI*1.5 ? false : true",
"as": "flipLabel"
},
{
"type": "formula",
"expr": "datum.datum.datum.Day === 1 ? 1 : 0",
"as": "opacity"
},
{
"type": "formula",
"expr": "datum['opacity'] === 1 ? datum['Date'] : null",
"as": "Date"
}
],
"type": "arc",
"encode": {
"update": {
"x": {"signal": "radialWidth/2"},
"y": {"signal": "radialHeight/2"},
"align": {"value": "center"},
"baseline": {"value": "top"},
"fill": {"signal": "darkColor"},
"startAngle": {"signal": "datum['datum']['startAngle']"},
"endAngle": {"signal": "datum['datum']['endAngle']"},
"innerRadius": {"signal": "monthAxisRadius-1.5"},
"outerRadius": {"signal": "monthAxisRadius"},
"opacity": {"field": "opacity"}
}
}
},
{
"name": "month_axis_hover_interactive",
"description": "month axis domain arcs that are used to capture the month and year",
"from": {"data": "month_axis_domain"},
"interactive": true,
"type": "arc",
"encode": {
"update": {
"x": {"signal": "radialWidth/2"},
"y": {"signal": "radialHeight/2"},
"align": {"value": "center"},
"baseline": {"value": "top"},
"fill": {"signal": "lightColor"},
"startAngle": {
"signal": "datum['startAngle']-bandwidth('dayAxisScale')/2"
},
"endAngle": {
"signal": "datum['endAngle']+bandwidth('dayAxisScale')/2"
},
"innerRadius": {
"signal": "monthAxisRadius-(min(radialWidth,radialHeight)/2)"
},
"outerRadius": {"signal": "radialWidth/2"},
"opacity": {"value": 0}
}
}
},
{
"name": "month_axis_hover",
"description": "month axis domain arcs that appear on hover to indicate the currently focused month",
"from": {"data": "month_axis_domain"},
"interactive": false,
"type": "arc",
"encode": {
"update": {
"x": {"signal": "radialWidth/2"},
"y": {"signal": "radialHeight/2"},
"align": {"value": "center"},
"baseline": {"value": "top"},
"fill": {"signal": "lightColor"},
"startAngle": {
"signal": "datum['startAngle']-bandwidth('dayAxisScale')/2"
},
"endAngle": {
"signal": "datum['endAngle']+bandwidth('dayAxisScale')/2"
},
"innerRadius": {
"signal": "monthAxisRadius-(min(radialWidth,radialHeight)/2)"
},
"outerRadius": {"signal": "monthAxisRadius+(height*0.042)"},
"opacity": {
"signal": "isValid(hoverMonth) && datum.FirstOfMonthDate === hoverMonth.FirstOfMonthDate && datum['opacity'] > 0 ? 0.3 : 0"
}
}
}
},
{
"name": "month_axis_label_hover",
"description": "month axis text labels that appear on hover to indicate the currently focused week",
"from": {"data": "month_axis_domain"},
"interactive": false,
"type": "text",
"encode": {
"update": {
"x": {"signal": "radialWidth/2"},
"y": {"signal": "radialHeight/2"},
"dy": {
"signal": "(datum['flipLabel'] ? -1 : 1) *-(0.0035*height)"
},
"fill": {"signal": "lightColor"},
"fontSize": {"signal": "0.0275*height"},
"align": {"value": "center"},
"text": {
"signal": "(datum['flipLabel'] ? '⮘ ' : '') + utcFormat(datum.FirstOfMonthDate, '%b %y') + (datum['flipLabel'] ? '' : ' ⮚')"
},
"font": {"value": "consolas"},
"baseline": {"signal": "datum['flipLabel'] ? 'top': 'bottom'"},
"radius": {"signal": "monthAxisRadius+(0.045*height)"},
"theta": {"signal": "datum['midAngle']"},
"angle": {
"signal": "(datum['flipLabel'] ? (-1*PI/PI*180) : 0) + datum['midAngle']*(180/PI)"
},
"opacity": {
"signal": "isValid(hoverMonth) && datum.FirstOfMonthDate === hoverMonth.FirstOfMonthDate && datum['opacity'] > 0 ? 1 : 0"
}
}
}
},
{
"name": "year_axis_domain",
"description": "year axis domain arcs",
"from": {"data": "day_bars"},
"interactive": false,
"transform": [
{
"type": "formula",
"expr": "datum['datum']['datum']['Year']",
"as": "Year"
},
{
"type": "formula",
"expr": "datum['datum']['theta']",
"as": "theta"
},
{
"type": "joinaggregate",
"fields": ["theta", "theta"],
"ops": ["min", "max"],
"groupby": ["Year"],
"as": ["startAngle", "endAngle"]
},
{
"type": "formula",
"expr": "datum['startAngle']+(datum['endAngle']-datum['startAngle'])/2",
"as": "midAngle"
},
{
"type": "formula",
"expr": "datum['midAngle'] < PI/2 || datum['midAngle'] > PI*1.5 ? false : true",
"as": "flipLabel"
},
{
"type": "window",
"ops": ["dense_rank"],
"fields": ["Year"],
"groupby": ["startAngle"],
"as": ["startAngleDR"]
},
{
"type": "formula",
"expr": "datum['startAngleDR'] === 1 ? 1 : 0",
"as": "opacity"
},
{
"type": "formula",
"expr": "datum['opacity'] === 1 ? datum['Date'] : null",
"as": "Date"
}
],
"type": "arc",
"encode": {
"update": {
"x": {"signal": "radialWidth/2"},
"y": {"signal": "radialHeight/2"},
"align": {"value": "center"},
"baseline": {"value": "top"},
"fill": {"signal": "semiLightColor"},
"startAngle": {"signal": "datum['datum']['startAngle']"},
"endAngle": {"signal": "datum['datum']['endAngle']"},
"innerRadius": {"signal": "yearAxisRadius-0.025*radialHeight"},
"outerRadius": {"signal": "yearAxisRadius+0.005*radialHeight"},
"opacity": {"field": "opacity"}
},
"hover": {"opacity": {"value": 0}}
}
},
{
"name": "year_axis_start_ticks",
"description": "pipe (|) text mark on the year axis that shows the start of a year",
"from": {"data": "year_axis_domain"},
"type": "text",
"encode": {
"update": {
"x": {"signal": "radialWidth/2"},
"y": {"signal": "radialHeight/2"},
"fill": {"signal": "datum.fill"},
"stroke": {"signal": "datum.fill"},
"strokeWidth": {"signal": "0.00329308452*height"},
"align": {"value": "left"},
"text": {"signal": "datum.datum.datum.Day === 1 ? '▮' : null"},
"fontSize": {"signal": "0.01646542261*height"},
"font": {"value": "consolas"},
"baseline": {"value": "bottom"},
"radius": {
"signal": "yearAxisRadius",
"offset": {"signal": "-0.0027442371*height"}
},
"theta": {
"field": "startAngle",
"offset": {"signal": "-0.00000109769*height"}
},
"angle": {"signal": "datum['startAngle']*(180/PI)"},
"tooltip": {"signal": "datum.datum.datum"}
}
}
},
{
"name": "year_axis_end_ticks",
"description": "pipe (|) text mark on the year axis that shows the end of a year",
"from": {"data": "year_axis_domain"},
"type": "text",
"encode": {
"update": {
"x": {"signal": "radialWidth/2"},
"y": {"signal": "radialHeight/2"},
"fill": {"signal": "datum.fill"},
"stroke": {"signal": "datum.fill"},
"strokeWidth": {"signal": "0.00329308452*height"},
"align": {"value": "right"},
"text": {
"signal": "datum.datum.datum.IsLastDayOfMonth ? '▮' : null"
},
"fontSize": {"signal": "0.01646542261*height"},
"font": {"value": "consolas"},
"baseline": {"value": "bottom"},
"radius": {
"signal": "yearAxisRadius",
"offset": {"signal": "-0.0027442371*height"}
},
"theta": {
"field": "endAngle",
"offset": {"signal": "0.00000329308*height"}
},
"angle": {"signal": "datum['endAngle']*(180/PI)"},
"tooltip": {"signal": "datum.datum.datum"}
}
}
},
{
"name": "year_axis_labels",
"description": "year axis text labels",
"from": {"data": "year_axis_domain"},
"interactive": false,
"type": "text",
"encode": {
"update": {
"x": {"signal": "radialWidth/2"},
"y": {
"signal": "radialHeight/2",
"offset": {
"signal": "(datum['flipLabel'] ? 0 : 1)*radialWidth*0.0035"
}
},
"fill": {"signal": "'#444'"},
"fontSize": {"signal": "0.0275*radialWidth"},
"fontWeight": {"value": "500"},
"align": {"value": "center"},
"text": {"signal": "datum.Year"},
"baseline": {"signal": "datum['flipLabel'] ? 'middle': 'middle'"},
"radius": {
"signal": "yearAxisRadius+0.005*radialHeight-((yearAxisRadius+0.005*radialHeight)-(yearAxisRadius-0.025*radialHeight))/2"
},
"theta": {"signal": "datum['midAngle']"},
"angle": {
"signal": "(datum['flipLabel'] ? (-1*PI/PI*180) : 0) + datum['midAngle']*(180/PI)"
},
"opacity": {"signal": "datum['opacity']"}
}
}
},
{
"name": "outer_content_background",
"description": "a filled arc with the same color as the canvas background. This arc prevents the month hover arcs from obsecuring the line graphs",
"interactive": true,
"type": "arc",
"encode": {
"update": {
"x": {"signal": "radialWidth/2"},
"y": {"signal": "radialHeight/2"},
"startAngle": {"value": 0},
"endAngle": {"signal": "2*PI"},
"innerRadius": {"value": 0},
"outerRadius": {"signal": "outerContentRadius"},
"fill": {"signal": "backgroundRGB"},
"stroke": {"signal": "darkColor"},
"strokeOpacity": {"value": 0.5}
}
}
},
{
"name": "placement_ready_group",
"description": "placement for the ready units",
"type": "group",
"interactive": false,
"encode": {
"update": {
"x": {"signal": "radialWidth/2 - outerContentRadius"},
"x2": {"signal": "radialWidth/2 + outerContentRadius"},
"y": {"signal": "radialHeight/2"},
"y2": {"signal": "radialHeight/2-outerContentRadius"},
"fill": {"value": "red"},
"fillOpacity": {"value": 0}
}
},
"marks": [
{
"name": "placement_interactive_arcs",
"from": {"data": "ready_placement"},
"type": "arc",
"interactive": true,
"encode": {
"update": {
"x": {"field": "cx"},
"y": {"field": "cy"},
"startAngle": {"field": "startAngle"},
"endAngle": {"field": "endAngle"},
"outerRadius": {
"field": "rowRadius",
"offset": {"signal": "bandwidth('xScalePlacementRow')/2"}
},
"innerRadius": {
"field": "rowRadius",
"offset": {"signal": "-bandwidth('xScalePlacementRow')/2"}
},
"fill": {"signal": "lightColor"},
"opacity": {"value": 0},
"tooltip": {
"signal": "{title: datum['Reporting Unit'], 'Field Comm': datum['Field Comm'], Delta: datum.Delta, 'C-Rating': datum.OVL || 'NR', 'Core Assmt.': datum.Assessment || 'NR'}"
}
}
}
},
{
"from": {"data": "ready_placement"},
"type": "text",
"interactive": false,
"encode": {
"update": {
"x": {"field": "cx"},
"y": {"field": "cy"},
"dy": {
"signal": "isValid(hoverUnit) && datum['Reporting Unit'] === hoverUnit['Reporting Unit'] ? fleetIconSize/10 : 0"
},
"text": {
"signal": "isValid(hoverUnit) && datum['Reporting Unit'] === hoverUnit['Reporting Unit'] ? '𝅛' : '|'"
},
"theta": {"field": "theta"},
"radius": {"field": "rowRadius"},
"angle": {"field": "angle"},
"fontSize": {
"signal": "isValid(hoverUnit) && datum['Reporting Unit'] === hoverUnit['Reporting Unit'] ? fleetIconSize*1.5 : fleetIconSize"
},
"align": {"value": "center"},
"baseline": {"value": "middle"},
"fill": {
"signal": "persistOVLColors || (isValid(hoverUnit) && datum['Reporting Unit'] === hoverUnit['Reporting Unit']) ? (readinessMetric === 'cRate' ? scale('scaleOVLColor', datum.OVL) : scale('scaleCoreColor', datum.Assessment)) : datum.isReady ? lightColor : darkColor"
}
}
}
}
]
},
{
"name": "placement_not_ready_group",
"description": "placement for the units that are not ready",
"type": "group",
"interactive": false,
"encode": {
"update": {
"x": {"signal": "radialWidth/2 - outerContentRadius"},
"x2": {"signal": "radialWidth/2 + outerContentRadius"},
"y": {"signal": "radialHeight/2"},
"y2": {"signal": "radialHeight/2-outerContentRadius"},
"fill": {"value": "red"},
"fillOpacity": {"value": 0}
}
},
"marks": [
{
"name": "placement_interactive_arcs",
"from": {"data": "notReady_placement"},
"type": "arc",
"interactive": true,
"encode": {
"update": {
"x": {"field": "cx"},
"y": {"field": "cy"},
"startAngle": {"field": "startAngle"},
"endAngle": {"field": "endAngle"},
"outerRadius": {
"field": "rowRadius",
"offset": {"signal": "bandwidth('xScalePlacementRow')/2"}
},
"innerRadius": {
"field": "rowRadius",
"offset": {"signal": "-bandwidth('xScalePlacementRow')/2"}
},
"fill": {"signal": "lightColor"},
"opacity": {"value": 0},
"tooltip": {
"signal": "{title: datum['Reporting Unit'], 'Field Comm': datum['Field Comm'], Delta: datum.Delta, 'C-Rating': datum.OVL || 'NR', 'Core Assmt.': datum.Assessment || 'NR'}"
}
}
}
},
{
"from": {"data": "notReady_placement"},
"type": "text",
"interactive": false,
"encode": {
"update": {
"x": {"field": "cx"},
"y": {"field": "cy"},
"dy": {
"signal": "isValid(hoverUnit) && datum['Reporting Unit'] === hoverUnit['Reporting Unit'] ? fleetIconSize/10 : 0"
},
"text": {
"signal": "isValid(hoverUnit) && datum['Reporting Unit'] === hoverUnit['Reporting Unit'] ? '𝅛' : '|'"
},
"theta": {"field": "theta"},
"radius": {"field": "rowRadius"},
"angle": {"field": "angle"},
"fontSize": {
"signal": "isValid(hoverUnit) && datum['Reporting Unit'] === hoverUnit['Reporting Unit'] ? fleetIconSize*1.5 : fleetIconSize"
},
"align": {"value": "center"},
"baseline": {"value": "middle"},
"fill": {
"signal": "persistOVLColors || (isValid(hoverUnit) && datum['Reporting Unit'] === hoverUnit['Reporting Unit']) ? (readinessMetric === 'cRate' ? scale('scaleOVLColor', datum.OVL) : scale('scaleCoreColor', datum.Assessment)) : datum.isReady ? lightColor : darkColor"
}
}
}
}
]
},
{
"name": "group_ready_text",
"type": "group",
"from": {"data": "unit_aggregates"},
"interactive": false,
"encode": {
"update": {
"x": {"signal": "radialWidth/2-innerContentRadius/1.5"},
"x2": {"signal": "radialWidth/2+innerContentRadius/1.5"},
"y": {"signal": "radialHeight/2-innerContentRadius/1.5"},
"y2": {"signal": "radialHeight/2+innerContentRadius/1.5"}
}
},
"marks": [
{
"name": "ready_percentage_text",
"type": "text",
"interactive": false,
"encode": {
"update": {
"x": {"signal": "(innerContentRadius/1.5)"},
"y": {"signal": "(innerContentRadius/1.5)"},
"dy": {"signal": "-innerContentRadius/2.15"},
"text": {
"signal": "format(parent.readyCount/parent.totalCount, '.2%')"
},
"fill": {"value": "#CCC"},
"baseline": {"value": "middle"},
"align": {"value": "center"},
"fontSize": {"signal": "0.0325*radialHeight"},
"fontWeight": {"value": 500}
}
}
},
{
"name": "ready_readytext",
"type": "text",
"interactive": false,
"from": {"data": "ready_percentage_text"},
"encode": {
"update": {
"x": {"signal": "(innerContentRadius/1.5)"},
"y": {"signal": "datum.bounds.y2"},
"text": {
"signal": "readinessMetric === 'cRate' ? 'Ready (C-Rating)' : 'Ready (Core Assmt.)'"
},
"fill": {"value": "#CCC"},
"baseline": {"value": "top"},
"align": {"value": "center"},
"fontSize": {"signal": "0.0275*radialHeight"},
"fontWeight": {"value": 500}
}
}
},
{
"name": "ready_count_text",
"type": "text",
"interactive": false,
"encode": {
"update": {
"x": {"signal": "(innerContentRadius/1.5)"},
"y": {"signal": "(innerContentRadius/1.5)"},
"dy": {"signal": "innerContentRadius/3.5"},
"text": {
"signal": "parent.readyCount + ' / ' + parent.totalCount"
},
"fill": {"signal": "mediumColor"},
"baseline": {"value": "middle"},
"align": {"value": "center"},
"fontSize": {"signal": "0.03*radialHeight"}
}
}
},
{
"name": "reporting_units_text",
"type": "text",
"interactive": false,
"from": {"data": "ready_count_text"},
"encode": {
"update": {
"x": {"signal": "(innerContentRadius/1.5)"},
"y": {"signal": "datum.bounds.y2"},
"dy": {"value": 2.5},
"text": {"value": "Reporting Units"},
"fill": {"signal": "mediumColor"},
"baseline": {"value": "top"},
"align": {"value": "center"},
"fontSize": {"signal": "0.03*radialHeight"}
}
}
}
]
},
{
"name": "header_group",
"type": "group",
"encode": {"update": {"x": {"signal": "10"}, "y": {"signal": "10"}}},
"marks": [
{
"name": "group_readinessMetricButtons",
"type": "group",
"marks": [
{
"name": "labelText",
"type": "text",
"encode": {
"update": {
"text": {"signal": "configButtons.label.text"},
"baseline": {"value": "bottom"},
"font": {"signal": "configButtons.label.font"},
"fontSize": {"signal": "configButtons.label.fontSize"},
"fontStyle": {"signal": "configButtons.label.fontStyle"},
"align": {"value": "left"},
"fill": {"signal": "configButtons.label.fill"}
}
}
},
{
"name": "readiness_metric_dummy_labels",
"description": "text marks that will be used by other button marks for reactive geometry",
"type": "text",
"from": {"data": "readinessMetricConfig"},
"interactive": false,
"encode": {
"update": {
"x": {
"signal": "configButtons.padding+datum.rowNumber*(height*0.075)"
},
"y": {
"signal": "configButtons.yOffset+configButtons.label.dy"
},
"fontSize": {"signal": "height*0.0165"},
"text": {"field": "label"},
"fill": {"value": "#666"},
"opacity": {"value": 0}
}
}
},
{
"name": "readiness_metric_button_background",
"description": "the background for the expand/collapse buttons",
"type": "rect",
"from": {"data": "readiness_metric_dummy_labels"},
"interactive": true,
"encode": {
"update": {
"x": {"signal": "datum.bounds.x1-configButtons.padding"},
"x2": {"signal": "datum.bounds.x2+configButtons.padding"},
"y": {"signal": "datum.bounds.y1-configButtons.padding"},
"y2": {"signal": "datum.bounds.y2+configButtons.padding"},
"cornerRadiusTopLeft": {
"signal": "datum.datum.rowNumber == 0 ? (0.0054884742*height) : 0"
},
"cornerRadiusBottomLeft": {
"signal": "datum.datum.rowNumber == 0 ? (0.0054884742*height) : 0"
},
"cornerRadiusTopRight": {
"signal": "datum.datum.rowNumber == 1 ? (0.0054884742*height) : 0"
},
"cornerRadiusBottomRight": {
"signal": "datum.datum.rowNumber == 1 ? (0.0054884742*height) : 0"
},
"fillOpacity": {"value": 1},
"stroke": {"signal": "background || '#fff'"},
"strokeWidth": {"value": 1},
"fill": {
"signal": "datum.datum.name === readinessMetric ? configButtons.selectedFill : configButtons.fill"
},
"opacity": {"value": 1},
"cursor": {"value": "pointer"},
"tooltip": {"signal": "datum.datum.tooltip"}
},
"hover": {"opacity": {"value": 0.9}}
}
},
{
"name": "readiness_metric_labels",
"description": "text marks that will be used by other button marks for reactive geometry",
"type": "text",
"from": {"data": "readiness_metric_dummy_labels"},
"interactive": false,
"encode": {
"update": {
"x": {"signal": "datum.x"},
"y": {"signal": "datum.y"},
"text": {"signal": "datum.datum.label"},
"fill": {"value": "#333"},
"fontSize": {"field": "fontSize"},
"opacity": {"value": 1}
}
}
},
{
"name": "info_icon",
"type": "symbol",
"from": {"data": "readiness_metric_labels"},
"interactive": false,
"encode": {
"update": {
"shape": {
"signal": "'M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM216 336h24V272H216c-13.3 0-24-10.7-24-24s10.7-24 24-24h48c13.3 0 24 10.7 24 24v88h8c13.3 0 24 10.7 24 24s-10.7 24-24 24H216c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-208a32 32 0 1 1 0 64 32 32 0 1 1 0-64z'"
},
"fill": {"value": "#b5cae1"},
"size": {"signal": "0.000006*height"},
"y": {"signal": "datum.bounds.y2+0.02*height"},
"x": {"signal": "0.001*height"},
"tooltip": {
"signal": "{title: 'Mouseover the radial timeline to explore readiness', 'By C-Rating': 'C-1 & C-2 considered \"Ready\"', 'By Core Assmt.': 'Y & Q considered \"Ready\"'}"
}
}
}
},
{
"name": "info_icon_interactive_rect",
"type": "rect",
"from": {"data": "info_icon"},
"interactive": true,
"encode": {
"update": {
"x": {"signal": "datum.bounds.x1"},
"x2": {"signal": "datum.bounds.x2"},
"y": {"signal": "datum.bounds.y1"},
"y2": {"signal": "datum.bounds.y2"},
"tooltip": {
"signal": "{title: 'Mouseover the radial timeline to explore readiness', 'By C-Rating': 'C-1 & C-2 considered \"Ready\"', 'By Core Assmt.': 'Y & Q considered \"Ready\"'}"
},
"fill": {"value": "transparent"}
}
}
}
]
}
]
}
],
"legends": [
{
"stroke": "scaleOVLColor",
"symbolType": "stroke",
"orient": "none",
"legendX": {"signal": "radialWidth/2-195"},
"legendY": {"signal": "0"},
"direction": "horizontal",
"encode": {
"symbols": {
"update": {
"angle": {"value": 90},
"size": {"signal": "0.5*height"},
"opacity": {"signal": " 0"}
}
},
"labels": {
"update": {
"y": {"signal": "height/2+(radialHeight/2)*0.95"},
"baseline": {"value": "bottom"},
"fill": {"signal": "scale('scaleOVLColor', datum.value)"},
"text": {
"signal": "((isNumber(datum.value) ? 'C-' : '') +datum.value) + '‎ ‎ ‎ ‎ ‎ ‎'"
},
"fontSize": {"signal": "16"},
"fontWeight": {"signal": "600"},
"opacity": {
"signal": "readinessMetric === 'core' || inrange(hoverMonth.startAngle, [2.6, 3.45]) ? 0 : persistOVLColors ? 1 : 0"
}
}
}
}
},
{
"stroke": "scaleCoreColor",
"symbolType": "stroke",
"orient": "none",
"legendX": {"signal": "radialWidth/2-120"},
"legendY": {"signal": "0"},
"direction": "horizontal",
"encode": {
"symbols": {
"update": {
"angle": {"value": 90},
"size": {"value": 200},
"opacity": {"signal": "0"}
}
},
"labels": {
"update": {
"y": {"signal": "height/2+(radialHeight/2)*0.95"},
"baseline": {"value": "bottom"},
"text": {"signal": "datum.value + '‎ ‎ ‎ ‎ ‎ ‎'"},
"fill": {"signal": "scale('scaleCoreColor', datum.value)"},
"fontSize": {"value": 16},
"opacity": {
"signal": "readinessMetric === 'cRate' || inrange(hoverMonth.startAngle, [2.6, 3.45]) ? 0 : persistOVLColors ? 1 : 0"
}
}
}
}
}
]
}
],
"scales": [
{
"name": "dayAxisScale",
"type": "band",
"domain": {
"data": "dataset_dates",
"field": "Date",
"sort": {"field": "Date"}
},
"range": [0, {"signal": "2*PI"}],
"paddingInner": {"signal": "xAxisOuterPaddingPercentage"},
"paddingOuter": {"signal": "xAxisOuterPaddingPercentage/2"}
},
{
"name": "xScalePlacementRow",
"type": "band",
"domain": {"signal": "sequence(1,placementNumberOfRows+1)"},
"range": {"signal": "[outerContentRadius-innerContentRadius, 0]"},
"padding": 0
},
{
"name": "scaleIsReadyColor",
"type": "ordinal",
"domain": [true, false],
"range": [{"signal": "lightColor"}, "#666"]
},
{
"name": "scaleOVLColor",
"type": "ordinal",
"domain": [1, 2, 3, 4, 5],
"range": [
"#59805C",
"#4CAF50 ",
"#FFEB3B ",
"#F44336",
{"signal": "mediumColor"}
]
},
{
"name": "scaleCoreColor",
"type": "ordinal",
"domain": ["Y", "Q", "N", "NR"],
"range": [
"#59805C",
"#FFEB3B ",
"#F44336",
{"signal": "mediumColor"},
{"signal": "mediumColor"}
]
}
],
"data": [
{
"name": "dataset",
"url": "https://raw.githubusercontent.com/Giammaria/PublicFiles/refs/heads/master/data/sf-notional-dataset.csv",
"format": {
"type": "csv",
"parse": {
"Field Comm": "string",
"Delta": "string",
"Reporting Unit": "string",
"Location": "string",
"Capability": "string",
"Component": "string",
"Squadron Type": "string",
"Mission": "string",
"Date": "date",
"P": "number",
"S": "number",
"R": "number",
"T": "number",
"OVL": "number",
"Override C-Rating": "number",
"Assessment": "string",
"Primary Degraders": "string",
"Secondary Degraders": "string",
"Month Look Back": "number",
"Last Month Lookback Filter": "string",
"Details Max Date": "date"
}
},
"transform": [
{"type": "filter", "expr": "datum.Mission === 'CORE'"},
{
"type": "filter",
"expr": "!isValid(datum.UIC) ? true : indexof(['SF2BS0','SF2BW0','SFSQK1','FFP090','FFDSX0','SFSQL1','SFSQG1','SFSQC1','SFSQ71','SFSQ51','SFSGL0','SF9NY0'], datum.UIC) < 0"
},
{
"type": "window",
"ops": ["dense_rank"],
"sort": {"field": "Reporting Unit"},
"as": ["dr"]
},
{
"type": "filter",
"expr": "windowLocationOrigin === '' ? datum.dr > 250 && datum.dr < 350 : true"
},
{
"type": "project",
"fields": [
"Date",
"Reporting Unit",
"Field Comm",
"Delta",
"OVL",
"Assessment"
],
"as": [
"Date",
"Reporting Unit",
"Field Comm",
"Delta",
"OVL",
"Assessment"
]
}
]
},
{
"name": "dataset_formatted",
"source": "dataset",
"transform": [
{
"type": "formula",
"expr": "isValid(datum.OVL) && isNumber(datum.OVL) && datum.OVL <= 5 ? datum.OVL : 'NR'",
"as": "OVL"
},
{
"type": "formula",
"expr": "+utcFormat(datum.Date, '%Y')",
"as": "Year"
},
{
"type": "formula",
"expr": "+utcFormat(datum.Date, '%m')",
"as": "MonthNumber"
},
{
"type": "formula",
"expr": "utcFormat(datum.Date, '%B')",
"as": "Month"
},
{
"type": "formula",
"expr": "utcFormat(datum.Date, '%b')",
"as": "MonthAbbreviation"
},
{
"type": "formula",
"expr": "toDate(utcFormat(datum.Date, '01-%b-%Y 00:00:00.000'))",
"as": "FirstOfMonthDate"
}
]
},
{
"name": "dataset_dates",
"source": "dataset_formatted",
"transform": [
{
"type": "aggregate",
"ops": ["min", "max"],
"fields": ["FirstOfMonthDate", "FirstOfMonthDate"],
"as": ["MinFirstOfMonthDate", "MaxFirstOfMonthDate"]
},
{
"type": "formula",
"expr": "toDate(utcFormat(timeOffset('day', timeOffset('month', datum.MaxFirstOfMonthDate, 1), -1), '%d-%b-%Y 00:00:00.000'))",
"as": "MaxFLastDayOfMonthDate"
},
{
"type": "formula",
"expr": "round((datum.MaxFLastDayOfMonthDate-datum.MinFirstOfMonthDate)/dayInMilliseconds)+1",
"as": "Days"
},
{"type": "formula", "expr": "sequence(0, datum.Days, 1)", "as": "Day"},
{"type": "flatten", "fields": ["Day"]},
{
"type": "formula",
"expr": "timeOffset('day', datum.MinFirstOfMonthDate, datum['Day'])",
"as": "Date"
},
{"type": "project", "fields": ["Date"]}
]
},
{
"name": "dataset_exploded",
"source": "dataset_formatted",
"transform": [
{
"type": "formula",
"expr": "toDate(utcFormat(timeOffset('day', timeOffset('month', datum.FirstOfMonthDate, 1), -1), '%d-%b-%Y 00:00:00.000'))",
"as": "LastOfMonthDate"
},
{
"type": "formula",
"expr": "round((datum.LastOfMonthDate-datum.FirstOfMonthDate)/dayInMilliseconds)+1",
"as": "Days"
},
{
"type": "aggregate",
"ops": ["count"],
"groupby": [
"Year",
"Month",
"MonthAbbreviation",
"Days",
"FirstOfMonthDate",
"LastOfMonthDate"
],
"as": ["count"]
},
{"type": "formula", "expr": "sequence(0, datum.Days, 1)", "as": "Day"},
{"type": "flatten", "fields": ["Day"]},
{
"type": "formula",
"expr": "timeOffset('day', datum.FirstOfMonthDate, datum['Day'])",
"as": "Date"
},
{"type": "formula", "expr": "datum.Day + 1", "as": "Day"},
{
"type": "formula",
"expr": "utcFormat(datum.Date, '%b%d') === utcFormat(datum.LastOfMonthDate, '%b%d')",
"as": "IsLastDayOfMonth"
},
{
"type": "project",
"fields": [
"FirstOfMonthDate",
"Date",
"Year",
"Month",
"MonthAbbreviation",
"Day",
"IsLastDayOfMonth"
]
}
]
},
{
"name": "detail_data_crate",
"source": "dataset_formatted",
"transform": [
{
"type": "filter",
"expr": "datum.FirstOfMonthDate === hoverMonth.FirstOfMonthDate"
},
{"type": "filter", "expr": "datum.OVL !== 'NR'"},
{
"type": "formula",
"expr": "isNumber(datum.OVL) && datum.OVL <= 2",
"as": "isReady"
},
{
"type": "formula",
"expr": "persistOVLColors || (isValid(datum.hoverUnit) && datum['Reporting Unit'] === datum.hoverUnit['Reporting Unit']) ? scale('scaleOVLColor', datum.OVL) : datum.isReady ? lightColor : darkColor",
"as": "Fill"
},
{
"type": "formula",
"expr": "indexof([1,2,3,4,5,'NR'], datum.OVL)",
"as": "OVLSort"
},
{"type": "collect", "sort": {"field": "OVLSort"}},
{
"type": "window",
"ops": ["dense_rank"],
"groupby": ["isReady"],
"as": ["index"]
},
{"type": "formula", "expr": "hoverUnit", "as": "hoverUnit"}
]
},
{
"name": "detail_data_core",
"source": "dataset_formatted",
"transform": [
{
"type": "filter",
"expr": "datum.FirstOfMonthDate === hoverMonth.FirstOfMonthDate"
},
{
"type": "formula",
"expr": "indexof(['Y','Q'], datum.Assessment)>=0",
"as": "isReady"
},
{"type": "collect", "sort": {"field": "OVL"}},
{
"type": "formula",
"expr": "indexof(['Q', 'Y', 'N', 'NR'], datum.Assessment) || 4",
"as": "AssessmentSort"
},
{"type": "collect", "sort": {"field": "AssessmentSort"}},
{
"type": "window",
"ops": ["dense_rank"],
"groupby": ["isReady"],
"as": ["index"]
},
{"type": "formula", "expr": "hoverUnit", "as": "hoverUnit"}
]
},
{
"name": "detail_data",
"on": [
{
"trigger": "readinessMetric",
"insert": "readinessMetric === 'cRate' ? data('detail_data_crate') : data('detail_data_core')",
"remove": true
}
],
"transform": [
{
"type": "formula",
"expr": "persistOVLColors",
"as": "persistOVLColors"
},
{"type": "collect", "sort": {"field": "index"}}
]
},
{
"name": "unit_aggregates",
"source": "detail_data",
"transform": [
{
"type": "aggregate",
"ops": ["count"],
"groupby": ["isReady"],
"as": ["rowCount"]
},
{"type": "pivot", "field": "isReady", "value": "rowCount"},
{"type": "formula", "expr": "datum.true || 0", "as": "readyCount"},
{"type": "formula", "expr": "datum.false || 0", "as": "notReadyCount"},
{
"type": "formula",
"expr": "(datum.readyCount || 0)+(datum.notReadyCount || 0)",
"as": "totalCount"
},
{
"type": "project",
"fields": ["readyCount", "notReadyCount", "totalCount"]
}
]
},
{
"name": "ready_placement",
"source": "detail_data",
"transform": [
{"type": "filter", "expr": "datum.isReady"},
{
"type": "formula",
"expr": "datum.index%placementNumberOfRows === 0 ? placementNumberOfRows : datum.index%placementNumberOfRows",
"as": "row"
},
{
"type": "formula",
"expr": "scale('xScalePlacementRow', datum.row)",
"as": "rowStartX"
},
{
"type": "formula",
"expr": "(outerContentRadius*2)-scale('xScalePlacementRow', datum.row)-bandwidth('xScalePlacementRow')",
"as": "rowEndX"
},
{
"type": "window",
"ops": ["dense_rank"],
"groupby": ["row"],
"as": ["seat"]
},
{
"type": "joinaggregate",
"ops": ["count"],
"groupby": ["row"],
"as": ["seatCount"]
},
{
"type": "joinaggregate",
"ops": ["max"],
"fields": ["seatCount"],
"as": ["seatCount"]
},
{
"type": "formula",
"expr": "(datum.rowEndX - datum.rowStartX)/2",
"as": "rowRadius"
},
{"type": "formula", "expr": "outerContentRadius", "as": "cx"},
{
"type": "formula",
"expr": "(radialHeight/2)-(radialHeight/2-outerContentRadius)",
"as": "cy"
},
{
"type": "formula",
"expr": "fleetPlacementRadialOffset+(-90/(180/PI))+(datum.seat/datum.seatCount)*(180/(180/PI)-2*fleetPlacementRadialOffset)",
"as": "theta"
},
{
"type": "window",
"ops": ["lag", "lead"],
"fields": ["theta", "theta"],
"groupby": ["row", "row"],
"as": ["lagTheta", "leadTheta"]
},
{
"type": "formula",
"expr": "isValid(datum.leadTheta) && isValid(datum.lagTheta) ? (datum.leadTheta - datum.lagTheta)/2 : 0",
"as": "thetaBandWidth"
},
{
"type": "joinaggregate",
"ops": ["max"],
"fields": ["thetaBandWidth"],
"as": ["thetaBandWidth"]
},
{
"type": "formula",
"expr": "datum.theta-datum.thetaBandWidth/2",
"as": "theta"
},
{"type": "formula", "expr": "datum.theta*(180/PI)", "as": "angle"},
{
"type": "formula",
"expr": "datum.thetaBandWidth || 0.11",
"as": "thetaBandWidth"
},
{
"type": "formula",
"expr": "datum.theta-(datum.thetaBandWidth/2)",
"as": "startAngle"
},
{
"type": "formula",
"expr": "datum.theta+(datum.thetaBandWidth/2)",
"as": "endAngle"
},
{
"type": "formula",
"expr": "readinessMetric === 'core' ? datum.Fill : persistOVLColors || (isValid(datum.hoverUnit) && datum['Reporting Unit'] === datum.hoverUnit['Reporting Unit']) ? scale('scaleOVLColor', datum.OVL) : datum.isReady ? lightColor : darkColor",
"as": "Fill"
},
{
"type": "formula",
"expr": "readinessMetric === 'cRate' ? datum.Fill : persistOVLColors || (isValid(datum.hoverUnit) && datum['Reporting Unit'] === datum.hoverUnit['Reporting Unit']) ? scale('scaleCoreColor', datum.Assessment) : datum.isReady ? lightColor : darkColor",
"as": "Fill"
}
]
},
{
"name": "notReady_placement",
"source": "detail_data",
"transform": [
{"type": "filter", "expr": "!datum.isReady"},
{
"type": "formula",
"expr": "datum.index%placementNumberOfRows === 0 ? placementNumberOfRows : datum.index%placementNumberOfRows",
"as": "row"
},
{
"type": "formula",
"expr": "scale('xScalePlacementRow', datum.row)",
"as": "rowStartX"
},
{
"type": "formula",
"expr": "(outerContentRadius*2)-scale('xScalePlacementRow', datum.row)-bandwidth('xScalePlacementRow')",
"as": "rowEndX"
},
{
"type": "window",
"ops": ["dense_rank"],
"groupby": ["row"],
"as": ["seat"]
},
{
"type": "joinaggregate",
"ops": ["count"],
"groupby": ["row"],
"as": ["seatCount"]
},
{
"type": "joinaggregate",
"ops": ["max"],
"fields": ["seatCount"],
"as": ["seatCount"]
},
{
"type": "formula",
"expr": "(datum.rowEndX - datum.rowStartX)/2",
"as": "rowRadius"
},
{"type": "formula", "expr": "outerContentRadius", "as": "cx"},
{
"type": "formula",
"expr": "(radialHeight/2)-(radialHeight/2-outerContentRadius)",
"as": "cy"
},
{
"type": "formula",
"expr": "fleetPlacementRadialOffset+(90/(180/PI))+(datum.seat/datum.seatCount)*(180/(180/PI)-2*fleetPlacementRadialOffset)",
"as": "theta"
},
{
"type": "window",
"ops": ["lag", "lead"],
"fields": ["theta", "theta"],
"groupby": ["row", "row"],
"as": ["lagTheta", "leadTheta"]
},
{
"type": "formula",
"expr": "isValid(datum.leadTheta) && isValid(datum.lagTheta) ? (datum.leadTheta - datum.lagTheta)/2 : 0",
"as": "thetaBandWidth"
},
{
"type": "joinaggregate",
"ops": ["max"],
"fields": ["thetaBandWidth"],
"as": ["thetaBandWidth"]
},
{
"type": "formula",
"expr": "datum.theta-datum.thetaBandWidth/2",
"as": "theta"
},
{"type": "formula", "expr": "datum.theta*(180/PI)", "as": "angle"},
{
"type": "formula",
"expr": "datum.thetaBandWidth || 0.11",
"as": "thetaBandWidth"
},
{
"type": "formula",
"expr": "datum.theta-(datum.thetaBandWidth/2)",
"as": "startAngle"
},
{
"type": "formula",
"expr": "datum.theta+(datum.thetaBandWidth/2)",
"as": "endAngle"
}
]
},
{
"name": "readinessMetricConfig",
"values": [
{
"rowNumber": 0,
"name": "cRate",
"label": "C-Rating",
"tooltip": "Readiness by C-Rating"
},
{
"rowNumber": 1,
"name": "core",
"label": "Core Assmt.",
"tooltip": "Readiness by Core Assessment"
}
]
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment