From a89ecf2699e562aa79c61eebee3110a94f6ea448 Mon Sep 17 00:00:00 2001 From: Perch Date: Thu, 23 Dec 2021 23:25:13 +0400 Subject: [PATCH 01/36] visualizer new design, add reference profile in profile viewer --- examples/Dataset_Profiler_Viewer.ipynb | 89 +- src/whylogs/viewer/index-hbs-cdn-all-in.html | 802 +++++++++++++++---- src/whylogs/viz/browser_viz.py | 22 +- 3 files changed, 714 insertions(+), 199 deletions(-) diff --git a/examples/Dataset_Profiler_Viewer.ipynb b/examples/Dataset_Profiler_Viewer.ipynb index 48b2c8809b..768ba8de08 100644 --- a/examples/Dataset_Profiler_Viewer.ipynb +++ b/examples/Dataset_Profiler_Viewer.ipynb @@ -18,7 +18,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "id": "1f0ab34a", "metadata": {}, "outputs": [], @@ -29,7 +29,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "fc04cc42", "metadata": {}, "outputs": [], @@ -59,7 +59,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 4, "id": "7ebc0b5f", "metadata": {}, "outputs": [], @@ -86,22 +86,24 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "id": "2e018520", "metadata": {}, "outputs": [], "source": [ "session = get_or_create_session()\n", - "with session.logger(\"mytestytest\",dataset_timestamp=datetime.datetime(2021, 6, 2)) as logger:\n", - " for _ in range(500):\n", - " logger.log({\"uniform_integers\": np.random.randint(0,50)})\n", - " logger.log({\"strings\": fake.name()})\n", - " logger.log({\"mixture_distribution\": np.random.choice(distribution, 1)[0]})\n", - " logger.log({\"nulls\": None})\n", - " logger.log({\"moah_data\":1})\n", - " logger.log({\"moah_data\":1})\n", - " logger.log({\"moah_data\":5})\n", - " profile=logger.profile" + "def profile_generator():\n", + " with session.logger(\"mytestytest\",dataset_timestamp=datetime.datetime(2021, 6, 2)) as logger:\n", + " for _ in range(500):\n", + " logger.log({\"uniform_integers\": np.random.randint(0,50)})\n", + " logger.log({\"strings\": fake.name()})\n", + " logger.log({\"mixture_distribution\": np.random.choice(distribution, 1)[0]})\n", + " logger.log({\"nulls\": None})\n", + " logger.log({\"moah_data\":1})\n", + " logger.log({\"moah_data\":1})\n", + " logger.log({\"moah_data\":5})\n", + " return logger.profile\n", + "profile=profile_generator()" ] }, { @@ -123,29 +125,54 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "id": "e293634d", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'/var/folders/pr/f715zv8x17b1v5vwydgv2gq40000gq/T/tmpabxku502.html'" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "profile_viewer(profiles=[profile], output_path=None)" ] }, + { + "cell_type": "markdown", + "id": "e9cebe5c", + "metadata": {}, + "source": [ + "### Logging reference profile" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "d36563e9", + "metadata": {}, + "outputs": [], + "source": [ + "reference_profile=profile_generator() " + ] + }, + { + "cell_type": "markdown", + "id": "56dcaef9", + "metadata": {}, + "source": [ + "### Add reference profile to viewer and open" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6a4eb38c", + "metadata": {}, + "outputs": [], + "source": [ + "profile_viewer(profiles=[profile], reference_profiles=[reference_profile], output_path=None,)" + ] + }, { "cell_type": "code", "execution_count": null, - "id": "d09732c5", + "id": "1b1d89e2", "metadata": {}, "outputs": [], "source": [] @@ -153,9 +180,9 @@ ], "metadata": { "kernelspec": { - "display_name": "whylogs-dev", + "display_name": "Python 3", "language": "python", - "name": "whylogs-dev" + "name": "python3" }, "language_info": { "codemirror_mode": { @@ -167,7 +194,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.6" + "version": "3.8.8" } }, "nbformat": 4, diff --git a/src/whylogs/viewer/index-hbs-cdn-all-in.html b/src/whylogs/viewer/index-hbs-cdn-all-in.html index 40141b4c37..e18aca1989 100644 --- a/src/whylogs/viewer/index-hbs-cdn-all-in.html +++ b/src/whylogs/viewer/index-hbs-cdn-all-in.html @@ -327,7 +327,6 @@ .wl-table-cell, .wl-table-head { - border-right: 1px solid var(--brandSecondary200); border-bottom: 1px solid var(--brandSecondary200); display: table-cell; padding: 12px 18px; @@ -438,7 +437,7 @@ } .wl-property-panel__chart--single { - padding-bottom: 30px; + padding-bottom: 17px; } .wl-property-panel__chart-title { @@ -666,6 +665,246 @@ color: var(--brandSecondary900); line-height: 1.5; } + + .wl__unlock-the-power { + padding: 15px; + position: fixed; + bottom: 0; + left: 0; + z-index: 999999; + background: #F1F6F6; + margin-bottom: 0 !important; + display: flex; + flex-direction: column; + align-items: center; + -webkit-box-shadow: 0px -6px 13px 0px rgba(0,0,0,0.32); + box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.05); + width: var(--SIDE-PANEL-WIDTH); + } + + .wl__btn-signup { + font-size: 13px; + } + + .wl__close-icon { + width: 15px; + height: 15px; + } + + .wl__close-icon img{ + width: 100%; + height: 100%; + cursor: pointer; + } + + .count-color { + color: black; + } + + .wl__burger_icon { + width: 18px; + height: 16px; + } + + .wl__burger_icon img{ + width: 100%; + height: 100%; + cursor: pointer; + } + + .space-between { + display: flex; + justify-content: space-between; + } + + .align-items { + display: flex; + align-items: center; + } + + .display-flex{ + display: flex; + } + + .feature-count-title { + font-size: 22px; + } + + .wl_filter-options { + background: rgba(255, 255, 255, 0.5); + border: 1px solid #DBE5E7; + box-sizing: border-box; + border-radius: 4px; + padding: 10px; + } + + .form-check-input:checked { + background-color: #0E7384; + border-color: #0E7384; + } + + .form-check-input[type=checkbox] { + border-radius: 1.25em; + } + + .not-clickable { + pointer-events: none; + } + + .wl_arrow-icon { + width: 15px; + height: 15px; + } + + .arrow-icon-container { + height: 100%; + cursor: pointer; + } + + .wl_list-item-dot { + background: #b0d2d7; + width: 8px; + height: 8px; + border-radius: 50px; + } + + .wl_filter-list-item { + display: flex; + align-items: center; + } + + .wl_filter-list-item>span{ + padding-left: 15px; + } + + .table-border-none { + border: none; + } + + .clickable-test-feature-wrap { + background: #F8FAFB; + } + + .clickable-test-feature-heading { + display: flex; + flex-direction: column; + } + + .clickable-test-feature-heading-wrap { + padding: 35px; + padding-bottom: 0; + border-bottom: 2px solid #EBF2F3; + } + + .pages-button-wrap { + display: flex; + align-items: flex-end; + } + + .page-button-wrap { + padding-right: 60px; + } + + .page-button{ + border: none; + background: no-repeat; + color: #6C757D; + font-weight: 600; + font-size: 16px; + letter-spacing: -0.01em; + padding-bottom: 25px; + } + + .activ-pages-button{ + color: #369BAC !important; + border-bottom: 4px solid #369BAC !important; + padding-bottom: 21px !important; + } + + .title p { + font-weight: 600; + font-size: 24px; + color: #313B3D; + } + + .info p { + font-weight: 600; + font-size: 12px; + color: #313B3D; + } + + .info div { + font-weight: 600; + font-size: 18px; + line-height: 20px; + color: #0E7384; + } + + .chart, .info { + display: flex; + flex-direction: column; + align-items: flex-end; + padding-right: 20px; + } + + .info:last-child { + padding: 0; + } + + .clickable-test-feature-body { + display: flex; + flex-direction: column; + } + + .chart-box-wrap { + display: flex; + justify-content: center; + } + + .chart-box { + width: 75%; + height: 310px; + border: 2px solid #EBF2F3; + background: #FFF; + border-radius: 4px; + } + + .chart-info-wrap { + display: flex; + align-items: flex-end; + } + + .chart-info { + display: flex; + align-items: flex-end; + } + + + @media only screen and (min-width: 1350px) { + .clickable-test-feature-body { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: center; + row-gap: 20px; + column-gap: 20px; + } + + .chart-box-wrap { + width: 45%; + display: flex; + justify-content: center; + margin-bottom: 0 !important; + } + + .chart-box { + width: 100%; + height: 310px; + border: 2px solid #EBF2F3; + background: #FFF; + border-radius: 4px; + } + } @@ -689,12 +928,12 @@
Profile viewer for whylogs
rel="noreferrer noopener" > @@ -716,98 +955,163 @@
Profile viewer for whylogs
-
+ -
+
@@ -1380,7 +1421,7 @@
Referenc
-
Feature
+
Feature
Reference
Diff from ref
@@ -1426,8 +1467,8 @@

{{@key}}

- {{{getGraphHtml this}}} - {{{getReferenceGraphHtml this}}} + {{{getGraphHtml this}}} + {{{getReferenceGraphHtml this}}}
@@ -2120,7 +2161,6 @@

Hold on! :)

`
${!chartValue ? chartTitle : ""}${chart}
`; const histChart = (chart) => `
Histogram Data
${chart}
`; - if (column.numberSummary) { if (column.frequentItems && column.frequentItems.items) { column.frequentItems.items.forEach((item, index) => { @@ -2296,27 +2336,6 @@

Hold on! :)

$("#compare-profile").removeClass("d-none"); } - $( window ).resize(function() { - const windowHeight = $(window).width() - if (windowHeight < 1350 || windowHeight > 1680) { - $(".chart-box-chart > svg").css("width", 600) - } - if (windowHeight < 1680) { - $(".chart-box-chart > svg").css("width", 450) - } - }); - - $("#frequent-item-button").on("click", function () { - $(".frequent-items-body").html(` - ${frequentItemBoxElement('item')} - ${frequentItemBoxElement('item')} - ${frequentItemBoxElement('item')} - ${frequentItemBoxElement('item')} - `); - - $(".clickable-test-feature-body").html(``); - }) - $featureSearch.addEventListener( "keyup", debounce((event) => { @@ -2435,22 +2454,27 @@

Hold on! :)

$(listItem[listItemIndex]).css("padding-left", "8px") }) + const chipElement = (chip) => `${chip}`; + const chipElementTableData = (value) => `${chipElement(value)}`; + const chartBoxElement = (chartTitle, chart) => `
${chartTitle}
-
${chart}
+
${chart}
` - const frequentItemBoxElement = (chartTitle) => ` -
-
-
${chartTitle}
+ const frequentItemBoxElement = (chartTitle, items) => ` +
+
+ + ${items} +
-
- ` +
+ ` const colorsForDistingushingCharts = (color, text) => `
@@ -2471,7 +2495,6 @@

Hold on! :)

` $(".clickable-test-feature-body").html(` ${chartBoxElement(colorsForDistingushingChartHTMLElement, getDoubleHistogramChart)} - ${chartBoxElement('', '')} `); } @@ -2484,7 +2507,17 @@

Hold on! :)

const getReferenceProfile = () => { return {{{reference_profile}}} } - function openReferencePropertyPanel( + function getProfileCharts(jsonData, key, getDoubleHistogramChart, getBarChart, getPositiveNegative) { + if (jsonData.numberSummary.isDiscrete) { + $("#page-button").text("Categorical Data") + categoricalDriftChart(getBarChart, getPositiveNegative) + } else { + $("#page-button").text("Numerical Data") + numericalDriftChart(getDoubleHistogramChart) + } + } + + function openProfilePropertyPanel( chart, propertyPanelData, infType @@ -2518,12 +2551,29 @@

Hold on! :)

$(".wl-table-wrap").addClass("wl-table-wrap--narrow"); } - function openProfilePropertyPanel( + function sortWithIndeces(toSort) { + for (let i = 0; i < toSort.length; i++) { + toSort[i] = [toSort[i], i]; + } + toSort.sort((left, right) => { + return right[0] < left[0] ? -1 : 1; + }); + toSort.sortIndices = []; + for (let j = 0; j < toSort.length; j++) { + toSort.sortIndices.push(toSort[j][1]); + toSort[j] = toSort[j][0]; + } + return toSort; + } + getBarChart, getPositiveNegativeChart, getDoubleHistogramChart, chart, - feature + feature, + items, + referenceItems, + key ) { const chartInfoItem = (drift, driftName) => `
@@ -2535,38 +2585,70 @@

Hold on! :)

const $clickableTestFeatureWrap = $(".clickable-test-feature-wrap"); const $pagesButtons = $(".page-button"); const $pagesButton = $pagesButtons[0]; - let chipString = ""; + let chipString = "", + frequentItemString = "", + referenceFrequentItemString = ""; - $(".clickable-test-feature-wrap").css("height", $( window ).height()) $pagesButtons.removeClass("activ-pages-button") $($pagesButton).addClass("activ-pages-button") $tableContent.addClass("d-none") $clickableTestFeatureWrap.removeClass("d-none") + const sortedItems = items.map((item) => +Object.values(item)[0]) + sortWithIndeces(sortedItems).sortIndices.forEach( + (item) => { + frequentItemString += ` + ${frequentItemBoxElement('',chipElementTableData(items[item].value))} + ` + referenceFrequentItemString += ` + ${frequentItemBoxElement('',chipElementTableData(referenceItems[item].value))} + ` + } + ); + $("#page-button").on("click", function () { - if (feature.numberSummary.isDiscrete) { - $("#page-button").text("Categorical Data") - categoricalDriftChart(getBarChart, getPositiveNegativeChart) - } else { - $("#page-button").text("Numerical Data") - numericalDriftChart(getDoubleHistogramChart) - } + getProfileCharts( + feature, + feature[0], + getDoubleHistogramChart, + getBarChart, + getPositiveNegativeChart + ) $(".frequent-items-body").html(``); }) - if (feature.numberSummary.isDiscrete) { - $("#page-button").text("Categorical Data") - categoricalDriftChart(getBarChart, getPositiveNegativeChart) - } else { - $("#page-button").text("Numerical Data") - numericalDriftChart(getDoubleHistogramChart) - } + getProfileCharts( + feature, + feature[0], + getDoubleHistogramChart, + getBarChart, + getPositiveNegativeChart + ) $(".frequent-items-body").html(``); + $("#frequent-item-button").on("click", function () { + $(".frequent-items-body").html(` +
+
+
+ items +
+ ${frequentItemString} +
+
+
+ reference profile items +
+ ${referenceFrequentItemString} +
+
+ `); + + $(".clickable-test-feature-body").html(``); + }) $("#chart").html(chart); chipString += ` - ${chartInfoItem(fixNumberTo(feature.numberSummary.stddev), "Drift from ref")} ${chartInfoItem(feature.numberSummary.count.toString(), "Total Count")} ${chartInfoItem(fixNumberTo(feature.numberSummary.mean), "Mean")} ` @@ -2607,27 +2689,32 @@

Hold on! :)

getBarChart, getPositiveNegativeChart ) { + $("#compare-profile").addClass("d-none") let profileColumns = null; let feature = JSON.parse(column); + let referenceFeature, + referencePropertyPanelData; const profileFromCSVfile = getReferenceProfile(); if (profileFromCSVfile) { - profileColumns = profileFromCSVfile.columns[key] - feature = profileColumns + referenceFeature = profileFromCSVfile.columns[key] + referencePropertyPanelData = getPropertyPanelData(referenceFeature); } let propertyPanelData = getPropertyPanelData(feature); - if (profileFromCSVfile && feature.numberSummary) { - openProfilePropertyPanel( + openReferencePropertyPanel( getBarChart, getPositiveNegativeChart, getDoubleHistogramChart, chart, - feature + feature, + propertyPanelData, + referencePropertyPanelData, + key ) } else { - openReferencePropertyPanel( + openProfilePropertyPanel( chart, propertyPanelData, infType @@ -2638,7 +2725,8 @@

Hold on! :)

function closeFeatureHeading() { const $tableContent = $("#table-content") const $clickableTestFeatureWrap = $(".clickable-test-feature-wrap") - + + $("#compare-profile").remove("d-none") $tableContent.removeClass("d-none") $clickableTestFeatureWrap.addClass("d-none") } diff --git a/src/whylogs/viewer/js/whylogs-script.js b/src/whylogs/viewer/js/whylogs-script.js index 89dbc63d1c..a74ffcd04e 100644 --- a/src/whylogs/viewer/js/whylogs-script.js +++ b/src/whylogs/viewer/js/whylogs-script.js @@ -142,20 +142,25 @@ ); } + const chipElement = (chip) => `${chip}`; + const chipElementTableData = (value) => `${chipElement(value)}`; + const chartBoxElement = (chartTitle, chart) => `
${chartTitle}
-
${chart}
+
${chart}
` - const frequentItemBoxElement = (chartTitle) => ` + const frequentItemBoxElement = (chartTitle, items) => `
-
-
${chartTitle}
-
+
+ + ${items} + +
` @@ -489,8 +494,32 @@ `); } - function openReferencePropertyPanel(items, key, chart, getDoubleHistogramChart, getBarChart, getPositiveNegative) { + function sortWithIndeces(toSort) { + for (let i = 0; i < toSort.length; i++) { + toSort[i] = [toSort[i], i]; + } + toSort.sort((left, right) => { + return right[0] < left[0] ? -1 : 1; + }); + toSort.sortIndices = []; + for (let j = 0; j < toSort.length; j++) { + toSort.sortIndices.push(toSort[j][1]); + toSort[j] = toSort[j][0]; + } + return toSort; + } + const getProfileCharts = (key, getDoubleHistogramChart, getBarChart, getPositiveNegative) => { + if (jsonData.columns[key].numberSummary.isDiscrete) { + $("#page-button").text("Categorical Data") + categoricalDriftChart(getBarChart, getPositiveNegative) + } else { + $("#page-button").text("Numerical Data") + numericalDriftChart(getDoubleHistogramChart) + } + } + + function openReferencePropertyPanel(referenceItems, items, profileItems, key, chart, getDoubleHistogramChart, getBarChart, getPositiveNegative) { const chartInfoItem = (drift, driftName) => `
${drift}
@@ -500,35 +529,74 @@ const $clickableTestFeatureWrap = $(".clickable-test-feature-wrap"); const $pagesButtons = $(".page-button"); const $pagesButton = $pagesButtons[0]; - let chipString = ""; - - $(".clickable-test-feature-wrap").css("height", $( window ).height()) + let chipString = "", + frequentItemString = "", + referenceFrequentItemString = ""; + $pagesButtons.removeClass("activ-pages-button") $($pagesButton).addClass("activ-pages-button") $tableContent.addClass("d-none") $clickableTestFeatureWrap.removeClass("d-none") - $("#page-button").on("click", function () { - if (jsonData.columns[key].numberSummary.isDiscrete) { - $("#page-button").text("Categorical Data") - categoricalDriftChart(getBarChart, getPositiveNegative) - } else { - $("#page-button").text("Numerical Data") - numericalDriftChart(getDoubleHistogramChart) + // frequentItemString += `${items.forEach((item) => {chipElementTableData(item.value)})}` + const sortedItems = items.map((item) => +Object.values(item)[0]) + // .sort((a,b) => +b.value - (+a.value)) + sortWithIndeces(sortedItems).sortIndices.forEach( + (item) => { + frequentItemString += ` + ${frequentItemBoxElement('',chipElementTableData(items[item].value))} + ` + referenceFrequentItemString += ` + ${frequentItemBoxElement('',chipElementTableData(referenceItems[item].value))} + ` } + ); + $("#page-button").on("click", function () { + getProfileCharts( + key, + getDoubleHistogramChart, + getBarChart, + getPositiveNegative + ) + $(".clickable-test-feature-body").removeClass("d-none"); $(".frequent-items-body").html(``); + referenceProfilePanelHeight() }) - if (jsonData.columns[key].numberSummary.isDiscrete) { - $("#page-button").text("Categorical Data") - categoricalDriftChart(getBarChart, getPositiveNegative) - } else { - $("#page-button").text("Numerical Data") - numericalDriftChart(getDoubleHistogramChart) - } + getProfileCharts( + key, + getDoubleHistogramChart, + getBarChart, + getPositiveNegative + ) + $(".clickable-test-feature-body").removeClass("d-none"); $(".frequent-items-body").html(``); + $("#frequent-item-button").on("click", function () { + $(".frequent-items-body").html(` +
+
+
+ items +
+ ${frequentItemString} +
+
+
+ reference profile items +
+ ${referenceFrequentItemString} +
+
+ `); + + $(".clickable-test-feature-body").addClass("d-none"); + + referenceProfilePanelHeight() + }) + + $("#chart").html(chart); chipString += ` @@ -542,8 +610,6 @@ function openProfilePropertyPanel(items, infType, chart) { $("#wl-property-panel__chart").html(chart); let chipString = ""; - const chipElement = (chip) => `${chip}`; - const chipElementTableData = (value) => `${chipElement(value)}`; const chipElementEstimation = (count) => `${count}`; items.forEach((item) => { @@ -567,12 +633,15 @@ $(".wl-table-wrap").addClass("wl-table-wrap--narrow"); } - function openPropertyPanel(items, infType, feature) { + function openPropertyPanel(referenceItems, items, infType, feature) { let getGraph = null, - getDoubleHistogramChart = null, - getBarChart = null, - getPositiveNegative = null, - getPropertyPanelGraph = null; + getPropertyPanelGraph = null, + getDoubleHistogramChart, + getBarChart, + getPositiveNegative, + currentWidth = 600, + propertyPanelGraph = true; + if (referencePropertyPanelData[feature[0]][0]) { items = referencePropertyPanelData[feature[0]][0] @@ -587,7 +656,16 @@ if (jsonData) { if (items.length > 0 && items !== "undefined") { if (referencePropertyPanelData[feature[0]][0]) { - openReferencePropertyPanel(referenceJsonData.columns[feature[0]], feature[0], getGraph, getDoubleHistogramChart, getBarChart, getPositiveNegative) + openReferencePropertyPanel( + referenceItems, + items, + referenceJsonData.columns[feature[0]], + feature[0], + getGraph, + getDoubleHistogramChart, + getBarChart, + getPositiveNegative + ) } else { openProfilePropertyPanel(items, infType, getPropertyPanelGraph) } @@ -856,6 +934,7 @@ "click", openPropertyPanel.bind( this, + referencePropertyPanelData[feature[0]][0], propertyPanelData[feature[0]][0], feature[1].inferredType[0].toLowerCase(), feature @@ -1320,17 +1399,6 @@ } } - $("#frequent-item-button").on("click", function () { - $(".frequent-items-body").html(` - ${frequentItemBoxElement('item')} - ${frequentItemBoxElement('item')} - ${frequentItemBoxElement('item')} - ${frequentItemBoxElement('item')} - `); - - $(".clickable-test-feature-body").html(``); - }) - $removeReferenceProfileButton.on("click", removeReferenceProfile) $(document).on("click", ".page-button", function(e) { From e960f5dde33a4a0bd86dcd09ef995505009af176 Mon Sep 17 00:00:00 2001 From: Perch2005 Date: Tue, 25 Jan 2022 17:17:51 +0300 Subject: [PATCH 30/36] responsiveness of chart text fixed. Add responsiveness to numerical and categorical charts of reference profile panel. --- src/whylogs/viewer/index-hbs-cdn-all-in.html | 107 ++++++++++++++----- src/whylogs/viewer/js/whylogs-script.js | 69 +++++++----- 2 files changed, 126 insertions(+), 50 deletions(-) diff --git a/src/whylogs/viewer/index-hbs-cdn-all-in.html b/src/whylogs/viewer/index-hbs-cdn-all-in.html index 94aa4a62d7..a897945f6e 100644 --- a/src/whylogs/viewer/index-hbs-cdn-all-in.html +++ b/src/whylogs/viewer/index-hbs-cdn-all-in.html @@ -408,6 +408,7 @@ color: var(--brandSecondary400); } .wl-table-cell__bedge { + display: flex; height: 24px; margin: 1px; padding: 2px 8px; @@ -923,7 +924,7 @@ justify-content: center; flex-direction: column; width: 75%; - height: 310px; + height: 340px; border: 2px solid #EBF2F3; background: #FFF; border-radius: 4px; @@ -1149,6 +1150,29 @@ width: 100%; } + .svg-container { + display: inline-block; + position: relative; + width: 85%; + padding-bottom: 34%; + vertical-align: top; + overflow: hidden; + } + + .graph-svg-container { + padding-bottom: 13%; + } + + .svg-content-responsive { + display: inline-block; + position: absolute; + left: 0; + } + + .reference-table-head { + min-width: 305px; + } + @media screen and (min-width: 1000px) { .desktop-content { display: block; @@ -1585,7 +1609,7 @@

Hold on! :)

} } - function generateChart(data, height = 75, width = 350, index = 0, referenceProfile = false) { + function generateChart(data, height = 75, width = 350, index = 0, referenceProfile = false, propertyPanelGraph = false) { const sizes = new GenerateChartParams(height, width, data, 5) const { MARGIN, @@ -1593,17 +1617,26 @@

Hold on! :)

SVG_HEIGHT, CHART_WIDTH, CHART_HEIGHT, - svgEl, maxYValue, xScale, yScale } = sizes const color = ["#369BAC", '#2683C9'] + let svgEl = d3.create("svg") + .attr("preserveAspectRatio", "xMinYMin meet") + .attr("viewBox", "30 0 320 400") + .classed("svg-content-responsive", true) + + if (propertyPanelGraph) { + svgEl = d3.create("svg").attr("width", width).attr("height", height); + } + // Add the y Axis if (!referenceProfile) { svgEl .append("g") + .style("font-size", "12") .attr("transform", "translate(" + MARGIN.LEFT + ", " + MARGIN.TOP + ")") .call(d3.axisLeft(yScale).tickValues([0, maxYValue/2, maxYValue])); } @@ -1652,7 +1685,7 @@

Hold on! :)

} } - function generateDoubleHistogramChart(key, data, referenceData) { + function generateDoubleHistogramChart(currentWidth, key, data, referenceData) { let histogramData = [], overlappedHistogramData = []; @@ -1660,21 +1693,29 @@

Hold on! :)

histogramData = chartData(data) overlappedHistogramData = chartData(referenceData.columns[key.data.key]) } - let yFormat, - xFormat; - const sizes = new GenerateChartParams(230, 600, histogramData) + + let yFormat, + xFormat, + sizes; + + sizes = new GenerateChartParams(230, currentWidth, histogramData) + const { MARGIN, SVG_WIDTH, SVG_HEIGHT, CHART_WIDTH, CHART_HEIGHT, - svgEl, maxYValue, xScale, yScale } = sizes + this.svgEl = d3.create("svg") + .attr("preserveAspectRatio", "xMinYMin meet") + .attr("viewBox", "0 0 600 400") + .classed("svg-content-responsive", true) + const xAxis = d3.axisBottom(xScale).ticks(SVG_WIDTH / 80, xFormat).tickSizeOuter(0); const yAxis = d3.axisLeft(yScale).ticks(SVG_HEIGHT / 40, yFormat); yFormat = yScale.tickFormat(100, yFormat); @@ -1734,7 +1775,7 @@

Hold on! :)

return svgEl._groups[0][0].outerHTML; } - function generateBarChart(key, datas, referenceData) { + function generateBarChart(currentWidth, key, datas, referenceData) { let histogramData = [], overlappedHistogramData = []; @@ -1752,18 +1793,22 @@

Hold on! :)

} }).slice(0, 20) - const sizes = new GenerateChartParams(230, 600, histogramData, undefined, 1) + const sizes = new GenerateChartParams(230, currentWidth, histogramData, undefined, 1) const { MARGIN, SVG_WIDTH, SVG_HEIGHT, CHART_WIDTH, CHART_HEIGHT, - svgEl, maxYValue, yScale } = sizes + this.svgEl = d3.create("svg") + .attr("preserveAspectRatio", "xMinYMin meet") + .attr("viewBox", "0 0 600 400") + .classed("svg-content-responsive", true) + const groups = d3.map(data, function(d){return(d.group)}).keys() const subgroups = ['profile', 'reference_profile'] @@ -1831,7 +1876,7 @@

Hold on! :)

return svgEl._groups[0][0].outerHTML; } - function generatePositiveNegativeChart(key, datas, referenceData) { + function generatePositiveNegativeChart(currentWidth, key, datas, referenceData) { let histogramData = [], overlappedHistogramData = []; @@ -1848,16 +1893,20 @@

Hold on! :)

let yFormat, xFormat; - const sizes = new GenerateChartParams(230, 600, histogramData, undefined, 1) + const sizes = new GenerateChartParams(230, currentWidth, histogramData, undefined, 1) const { MARGIN, SVG_WIDTH, SVG_HEIGHT, CHART_WIDTH, - CHART_HEIGHT, - svgEl + CHART_HEIGHT } = sizes + this.svgEl = d3.create("svg") + .attr("preserveAspectRatio", "xMinYMin meet") + .attr("viewBox", "0 0 600 400") + .classed("svg-content-responsive", true) + const y0 = Math.max(Math.abs(d3.min(data)), Math.abs(d3.max(data))); const yScale = d3.scaleLinear() @@ -1935,7 +1984,11 @@

Hold on! :)

} else if (referenceColumn.frequentItems === undefined){ return ''; } - return generateChart(data, ...[,,], chartColor, chartValue); + return ` +
+ ${generateChart(data, ...[,,], chartColor, chartValue)} +
+ `; } function formatLabelDate(timestamp) { @@ -2142,9 +2195,9 @@

Hold on! :)

Handlebars.registerHelper("getGraphHtml",(column,key) => graph(column, key, null)); Handlebars.registerHelper("getReferenceGraphHtml",(column,key) => graph(column, key, profileFromCSVfile)); - Handlebars.registerHelper("getDoubleHistogramChart",(column,key) => generateDoubleHistogramChart(key, column, profileFromCSVfile)); - Handlebars.registerHelper("getBarChart",(column,key) => generateBarChart(key, column, profileFromCSVfile)); - Handlebars.registerHelper("getPositiveNegativeChart",(column,key) => generatePositiveNegativeChart(key, column, profileFromCSVfile)); + Handlebars.registerHelper("getDoubleHistogramChart",(column,key) => generateDoubleHistogramChart(600, key, column, profileFromCSVfile)); + Handlebars.registerHelper("getBarChart",(column,key) => generateBarChart(600, key, column, profileFromCSVfile)); + Handlebars.registerHelper("getPositiveNegativeChart",(column,key) => generatePositiveNegativeChart(600, key, column, profileFromCSVfile)); Handlebars.registerHelper("getPropertyPanelGraphHtml", function (column, key) { let chartString = ""; @@ -2179,20 +2232,21 @@

Hold on! :)

}); }); } - if (!!profileFromCSVfile) { + if (profileFromCSVfile) { data = chartData(profileFromCSVfile.columns[columnKey]) } if (column.numberSummary.isDiscrete) { - if (freqData.length > 0) chartString += freqChart(generateChart(freqData, chartHeight, chartWidth, undefined, chartValue)); - if (histData.length > 0 && !chartValue) chartString += histChart(generateChart(histData, 130)); + if (freqData.length > 0) chartString += freqChart(generateChart(freqData, chartHeight, chartWidth, undefined, chartValue, true)); + if (histData.length > 0 && !chartValue) chartString += histChart(generateChart(histData, 130, ...[,,,], true)); } else { - if (histData.length > 0 && !chartValue) chartString += histChart(generateChart(histData, 130)); - if (freqData.length > 0) chartString += freqChart(generateChart(freqData, chartHeight, chartWidth, undefined, chartValue)); + if (histData.length > 0 && !chartValue) chartString += histChart(generateChart(histData, 130, ...[,,,], true)); + if (freqData.length > 0) chartString += freqChart(generateChart(freqData, chartHeight, chartWidth, undefined, chartValue, true)); } - if (!!profileFromCSVfile) { + if (profileFromCSVfile && Object.values(profileFromCSVfile)) { chartString = ''; - chartString += generateChart(data, 50, 280, 0, true); + let propertyPanelGraph = true; + chartString += generateChart(data, 50, 280, 0, true, propertyPanelGraph); } } return chartString; @@ -2325,6 +2379,7 @@

Hold on! :)

} if(checkCurrentProfile(true, false)) { + $(".svg-container").css("padding-bottom", "27%") $("#diff-from-ref").addClass("d-none") $(".diff-from-ref-table-cell").addClass("d-none") $("#reference-profile-time-stamp").addClass("d-none"); diff --git a/src/whylogs/viewer/js/whylogs-script.js b/src/whylogs/viewer/js/whylogs-script.js index a74ffcd04e..fe44dc9a2d 100644 --- a/src/whylogs/viewer/js/whylogs-script.js +++ b/src/whylogs/viewer/js/whylogs-script.js @@ -170,7 +170,6 @@ ${text}
` - let chartWidth = 600; class GenerateChartParams { constructor(height, width, data, bottomMargin=20, topMargin=5) { @@ -197,13 +196,19 @@ } } - function getGraphHtml(data, height = 75, width = 350, index = 0, referenceProfile = false) { + const referenceProfilePanelHeight = () => { + const pageHeight = $(document).height() - 48; + if ($(".clickable-test-feature-wrap").height() <= pageHeight) { + $(".clickable-test-feature-wrap").css("height", pageHeight) + } else { + $(".clickable-test-feature-wrap").css("height", "auto") + } + } + + function getGraphHtml(data, height = 75, width = 350, index = 0, referenceProfile = false, propertyPanelGraph = false) { const sizes = new GenerateChartParams(height, width, data, 5) - const { + let { MARGIN, - SVG_WIDTH, - SVG_HEIGHT, - CHART_WIDTH, CHART_HEIGHT, svgEl, maxYValue, @@ -212,6 +217,10 @@ } = sizes const color = ["#369BAC", '#2683C9'] + if (propertyPanelGraph) { + svgEl = d3.create("svg").attr("width", width).attr("height", height); + } + // Add the y Axis if (!referenceProfile) { svgEl @@ -236,22 +245,26 @@ return svgEl._groups[0][0].outerHTML; } - function generateDoubleHistogramChart(histogramData, overlappedHistogramData) { + function generateDoubleHistogramChart(currentWidth, histogramData, overlappedHistogramData) { let yFormat, xFormat; - const sizes = new GenerateChartParams(230, chartWidth, histogramData) - const { + const sizes = new GenerateChartParams(230, currentWidth, histogramData) + let { MARGIN, SVG_WIDTH, SVG_HEIGHT, CHART_WIDTH, CHART_HEIGHT, svgEl, - maxYValue, xScale, yScale } = sizes + + svgEl = d3.create("svg") + .attr("preserveAspectRatio", "xMinYMin meet") + .attr("viewBox", "0 0 600 400") + .classed("svg-content-responsive", true) const xAxis = d3.axisBottom(xScale).ticks(SVG_WIDTH / 80, xFormat).tickSizeOuter(0); const yAxis = d3.axisLeft(yScale).ticks(CHART_HEIGHT / 40, yFormat); @@ -270,7 +283,7 @@ .attr("fill", "currentColor") .attr("text-anchor", "start")); - svgEl.append("g") + svgEl.append("g").append("g") .attr("transform", `translate(0,${SVG_HEIGHT - MARGIN.BOTTOM})`) .call(xAxis) .call(g => g.select(".domain").remove()) @@ -312,7 +325,7 @@ return svgEl._groups[0][0].outerHTML; } - function generateBarChart(histogramData, overlappedHistogramData) { + function generateBarChart(currentWidth, histogramData, overlappedHistogramData) { let yFormat, xFormat; const data = histogramData.map((profile, index) => { @@ -323,20 +336,23 @@ } }).slice(0, 20) - const sizes = new GenerateChartParams(230, chartWidth, histogramData, undefined, 1) - const { + const sizes = new GenerateChartParams(230, currentWidth, histogramData, undefined, 1) + let { MARGIN, SVG_WIDTH, SVG_HEIGHT, CHART_WIDTH, CHART_HEIGHT, svgEl, - maxYValue, xScale, yScale } = sizes - const groups = d3.map(data, function(d){return(d.group)}).keys() + svgEl = d3.create("svg") + .attr("preserveAspectRatio", "xMinYMin meet") + .attr("viewBox", "0 0 600 400") + .classed("svg-content-responsive", true) + const subgroups = ['profile', 'reference_profile'] xScale.padding([0.3]) @@ -399,7 +415,7 @@ return svgEl._groups[0][0].outerHTML; } - function generatePositiveNegativeChart(histogramData, overlappedHistogramData) { + function generatePositiveNegativeChart(currentWidth, histogramData, overlappedHistogramData) { const data = histogramData.map((value, index) => { const difference = value.axisY - overlappedHistogramData[index].axisY const negativeValues = difference < 0 ? difference : 0 @@ -409,8 +425,8 @@ let yFormat, xFormat; - const sizes = new GenerateChartParams(230, chartWidth, histogramData, undefined, 1) - const { + const sizes = new GenerateChartParams(230, currentWidth, histogramData, undefined, 1) + let { MARGIN, SVG_WIDTH, SVG_HEIGHT, @@ -419,6 +435,11 @@ svgEl } = sizes + svgEl = d3.create("svg") + .attr("preserveAspectRatio", "xMinYMin meet") + .attr("viewBox", "0 0 600 400") + .classed("svg-content-responsive", true) + const y0 = Math.max(Math.abs(d3.min(data)), Math.abs(d3.max(data))); const yScale = d3.scaleLinear() @@ -483,7 +504,6 @@ ` $(".clickable-test-feature-body").html(` ${chartBoxElement(colorsForDistingushingChartHTMLElement, getDoubleHistogramChart)} - ${chartBoxElement('', '')} `); } @@ -605,6 +625,7 @@ ${chartInfoItem(fixNumberTo(items.numberSummary.mean), "Mean")} ` $(".chart-info").html(chipString); + referenceProfilePanelHeight() } function openProfilePropertyPanel(items, infType, chart) { @@ -644,11 +665,11 @@ if (referencePropertyPanelData[feature[0]][0]) { + getDoubleHistogramChart = generateDoubleHistogramChart(currentWidth, feature[1].chartData[0], feature[1].chartData[1]) + getBarChart = generateBarChart(currentWidth, feature[1].chartData[0], feature[1].chartData[1]) + getPositiveNegative = generatePositiveNegativeChart(currentWidth, feature[1].chartData[0], feature[1].chartData[1]) items = referencePropertyPanelData[feature[0]][0] - getGraph = getGraphHtml(feature[1].chartData[1], 50, 280, 0, true) - getDoubleHistogramChart = generateDoubleHistogramChart(feature[1].chartData[0], feature[1].chartData[1]) - getBarChart = generateBarChart(feature[1].chartData[0], feature[1].chartData[1]), - getPositiveNegative = generatePositiveNegativeChart(feature[1].chartData[0], feature[1].chartData[1]) + getGraph = getGraphHtml(feature[1].chartData[1], 50, 280, 0, true, propertyPanelGraph) } getPropertyPanelGraph = getPropertyPanelGraphHtml(jsonData.columns[feature[0]], feature[0]) From cfb63f49988f2955bcb0494c7fe2534b017b3eda Mon Sep 17 00:00:00 2001 From: Perch2005 Date: Tue, 25 Jan 2022 17:41:47 +0300 Subject: [PATCH 31/36] fix reference profile panel height --- src/whylogs/viewer/index-hbs-cdn-all-in.html | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/whylogs/viewer/index-hbs-cdn-all-in.html b/src/whylogs/viewer/index-hbs-cdn-all-in.html index a897945f6e..bccad836dc 100644 --- a/src/whylogs/viewer/index-hbs-cdn-all-in.html +++ b/src/whylogs/viewer/index-hbs-cdn-all-in.html @@ -409,6 +409,7 @@ } .wl-table-cell__bedge { display: flex; + align-items: center; height: 24px; margin: 1px; padding: 2px 8px; @@ -2621,6 +2622,16 @@

Hold on! :)

return toSort; } + function referenceProfilePanelHeight() { + const pageHeight = $(document).height() - 48; + if ($(".clickable-test-feature-wrap").height() <= pageHeight) { + $(".clickable-test-feature-wrap").css("height", pageHeight) + } else { + $(".clickable-test-feature-wrap").css("height", "auto") + } + } + + function openReferencePropertyPanel( getBarChart, getPositiveNegativeChart, getDoubleHistogramChart, @@ -2671,6 +2682,7 @@

Hold on! :)

) $(".frequent-items-body").html(``); + referenceProfilePanelHeight() }) getProfileCharts( @@ -2701,6 +2713,7 @@

Hold on! :)

`); $(".clickable-test-feature-body").html(``); + referenceProfilePanelHeight() }) $("#chart").html(chart); chipString += ` @@ -2708,6 +2721,7 @@

Hold on! :)

${chartInfoItem(fixNumberTo(feature.numberSummary.mean), "Mean")} ` $(".chart-info").html(chipString); + referenceProfilePanelHeight() } function getPropertyPanelData(feature) { From e68dcb4fac99655ee12233e63ec89f324500b646 Mon Sep 17 00:00:00 2001 From: Perch2005 Date: Tue, 25 Jan 2022 17:43:10 +0300 Subject: [PATCH 32/36] delete Drift from ref --- src/whylogs/viewer/js/whylogs-script.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/whylogs/viewer/js/whylogs-script.js b/src/whylogs/viewer/js/whylogs-script.js index fe44dc9a2d..0415398a8e 100644 --- a/src/whylogs/viewer/js/whylogs-script.js +++ b/src/whylogs/viewer/js/whylogs-script.js @@ -620,9 +620,8 @@ $("#chart").html(chart); chipString += ` - ${chartInfoItem(fixNumberTo(items.numberSummary.stddev), "Drift from ref")} - ${chartInfoItem(items.numberSummary.count.toString(), "Total Count")} - ${chartInfoItem(fixNumberTo(items.numberSummary.mean), "Mean")} + ${chartInfoItem(profileItems.numberSummary.count.toString(), "Total Count")} + ${chartInfoItem(fixNumberTo(profileItems.numberSummary.mean), "Mean")} ` $(".chart-info").html(chipString); referenceProfilePanelHeight() From 53ed5cb604e46536f490b4d1f8fef6557cbc59e1 Mon Sep 17 00:00:00 2001 From: Perch2005 Date: Tue, 25 Jan 2022 17:50:11 +0300 Subject: [PATCH 33/36] fix table head position of histograms --- src/whylogs/viewer/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/whylogs/viewer/index.html b/src/whylogs/viewer/index.html index fd58b3ee18..50dbd7bf77 100644 --- a/src/whylogs/viewer/index.html +++ b/src/whylogs/viewer/index.html @@ -302,8 +302,8 @@
2020-02-26 12:
-
Feature
-
Reference
+
Feature
+
Reference
Diff from ref
Frequent items
From de0c653c85783cf869fc3dfb8ba1c74d6630d749 Mon Sep 17 00:00:00 2001 From: Jirayr-Solvee Date: Tue, 8 Feb 2022 21:49:56 +0400 Subject: [PATCH 34/36] indentation fixes --- src/whylogs/viz/browser_viz.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/whylogs/viz/browser_viz.py b/src/whylogs/viz/browser_viz.py index e41f26959b..385e2b71e4 100644 --- a/src/whylogs/viz/browser_viz.py +++ b/src/whylogs/viz/browser_viz.py @@ -35,8 +35,9 @@ def profile_viewer(profiles: List[DatasetProfile] = None, reference_profiles: Li "More than one profile not implemented yet, default to first profile in the list ") profile_jsons = [message_to_json(each_prof.to_summary()) for each_prof in profiles] if reference_profiles: - reference_profile_jsons = [message_to_json(each_prof.to_summary()) - for each_prof in reference_profiles] + reference_profile_jsons = [ + message_to_json(each_prof.to_summary()) for each_prof in reference_profiles + ] else: index_path = os.path.abspath(os.path.join(_MY_DIR, os.pardir, "viewer", "index.html")) @@ -54,8 +55,10 @@ def profile_viewer(profiles: List[DatasetProfile] = None, reference_profiles: Li template = compiler.compile(source) # replace handlebars for json profiles if reference_profiles: - output_index = template( - {"profile_from_whylogs": profile_jsons[0], "reference_profile": reference_profile_jsons[0]}) + output_index = template({ + "profile_from_whylogs": profile_jsons[0], + "reference_profile": reference_profile_jsons[0] + }) else: output_index = template( {"profile_from_whylogs": profile_jsons[0]}) From 255923916031d6827427dfacc0d0812635fcc99b Mon Sep 17 00:00:00 2001 From: Jirayr-Solvee Date: Tue, 8 Feb 2022 23:40:50 +0400 Subject: [PATCH 35/36] formating fixes --- src/whylogs/viz/browser_viz.py | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/src/whylogs/viz/browser_viz.py b/src/whylogs/viz/browser_viz.py index 385e2b71e4..fea9b80393 100644 --- a/src/whylogs/viz/browser_viz.py +++ b/src/whylogs/viz/browser_viz.py @@ -21,8 +21,7 @@ def profile_viewer(profiles: List[DatasetProfile] = None, reference_profiles: Li except ImportError as e: Compiler = None logger.debug(str(e)) - logger.debug( - "Unable to load pybars; install pybars3 to load profile from directly from the current session ") + logger.debug("Unable to load pybars; install pybars3 to load profile from directly from the current session ") index_path = os.path.abspath(os.path.join(_MY_DIR, os.pardir, "viewer", "index.html")) webbrowser.open_new_tab(f"file:{index_path}#") @@ -31,21 +30,17 @@ def profile_viewer(profiles: List[DatasetProfile] = None, reference_profiles: Li # create json output from profiles if profiles: if len(profiles) > 1: - logger.warning( - "More than one profile not implemented yet, default to first profile in the list ") + logger.warning("More than one profile not implemented yet, default to first profile in the list ") profile_jsons = [message_to_json(each_prof.to_summary()) for each_prof in profiles] if reference_profiles: - reference_profile_jsons = [ - message_to_json(each_prof.to_summary()) for each_prof in reference_profiles - ] + reference_profile_jsons = [message_to_json(each_prof.to_summary()) for each_prof in reference_profiles] else: index_path = os.path.abspath(os.path.join(_MY_DIR, os.pardir, "viewer", "index.html")) webbrowser.open_new_tab(f"file:{index_path}#") return None - index_path = os.path.abspath(os.path.join( - _MY_DIR, os.pardir, "viewer", "index-hbs-cdn-all-in.html")) + index_path = os.path.abspath(os.path.join(_MY_DIR, os.pardir, "viewer", "index-hbs-cdn-all-in.html")) with open(index_path, "r") as file_with_template: source = file_with_template.read() @@ -55,13 +50,9 @@ def profile_viewer(profiles: List[DatasetProfile] = None, reference_profiles: Li template = compiler.compile(source) # replace handlebars for json profiles if reference_profiles: - output_index = template({ - "profile_from_whylogs": profile_jsons[0], - "reference_profile": reference_profile_jsons[0] - }) + output_index = template({"profile_from_whylogs": profile_jsons[0], "reference_profile": reference_profile_jsons[0]}) else: - output_index = template( - {"profile_from_whylogs": profile_jsons[0]}) + output_index = template({"profile_from_whylogs": profile_jsons[0]}) if not output_path: output_path = tempfile.mkstemp(suffix=".html")[1] From a3b879bc843f29d29e199a9c5dcdac7a44ff8215 Mon Sep 17 00:00:00 2001 From: Jirayr-Solvee Date: Wed, 9 Feb 2022 00:09:46 +0400 Subject: [PATCH 36/36] add test for viewer --- tests/unit/viz/test_profile_viewer.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/unit/viz/test_profile_viewer.py b/tests/unit/viz/test_profile_viewer.py index 66d76b7c5e..24162aef98 100644 --- a/tests/unit/viz/test_profile_viewer.py +++ b/tests/unit/viz/test_profile_viewer.py @@ -8,7 +8,7 @@ from whylogs.viz import profile_viewer -def test_profile_viewer(tmpdir, local_config_path): +def test_profile_viewer_without_reference(tmpdir, local_config_path): config = load_config(local_config_path) session = session_from_config(config) @@ -22,3 +22,19 @@ def test_profile_viewer(tmpdir, local_config_path): result = profile_viewer(profiles=[profile], output_path=tmpdir + "my_test.html") assert os.path.exists(tmpdir + "my_test.html") assert result == tmpdir + "my_test.html" + + +def test_profile_viewer_with_reference(tmpdir, local_config_path): + + config = load_config(local_config_path) + session = session_from_config(config) + + with session.logger("mytestytest", dataset_timestamp=datetime.datetime(2021, 6, 2)) as logger: + for _ in range(5): + logger.log({"uniform_integers": np.random.randint(0, 50)}) + logger.log({"nulls": None}) + + profile = logger.profile + result = profile_viewer(profiles=[profile], reference_profiles=[profile], output_path=tmpdir + "my_test_ref.html") + assert os.path.exists(tmpdir + "my_test_ref.html") + assert result == tmpdir + "my_test_ref.html"