Files
qbit-data-analysis/src/main/java/com/kingsrook/qbits/dataanalysis/api/RelationshipSchemas.java
T
james.maesandClaude Opus 5.5 20b8223ce8 feat(compare): compare, distribution shift, correlation, scatter and crosstabs
Extension 1.2.0: compare two filters field by field with deltas and
significance (two-proportion z, Welch's t, chi-square with validity
rules and plain sentences), distribution shift over time with PSI, a
pushed-down Pearson correlation matrix with sampled scatter and trend,
and crosstabs with chi-square and Cramer's V. Pure-Java statistics
checked against scipy reference values; the privacy guard, field access
and drills apply as for profiles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 19:37:03 -05:00

664 lines
39 KiB
Java

/*
* QQQ - Low-code Application Framework for Engineers.
* Copyright (C) 2021-2025. Kingsrook, LLC
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
* contact@kingsrook.com
* https://github.com/Kingsrook/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.kingsrook.qbits.dataanalysis.api;
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
import com.kingsrook.qqq.middleware.javalin.schemabuilder.ToSchema;
import com.kingsrook.qqq.middleware.javalin.schemabuilder.annotations.OpenAPIDescription;
import com.kingsrook.qqq.openapi.model.Schema;
import com.kingsrook.qqq.openapi.model.Type;
/*******************************************************************************
** Explicit version-one contracts for compare and relationships.
*******************************************************************************/
public class RelationshipSchemas
{
/*******************************************************************************
** Register every referenced response and request component.
*******************************************************************************/
public static Map<String, Schema> components()
{
Map<String, Schema> result = new LinkedHashMap<>();
result.put("DataAnalysisCompareRequestV1", new DataAnalysisCompareRequestV1().toSchema());
result.put("DataAnalysisShiftRequestV1", new DataAnalysisShiftRequestV1().toSchema());
result.put("DataAnalysisCorrelationRequestV1", new DataAnalysisCorrelationRequestV1().toSchema());
result.put("DataAnalysisScatterRequestV1", new DataAnalysisScatterRequestV1().toSchema());
result.put("DataAnalysisCrosstabRequestV1", new DataAnalysisCrosstabRequestV1().toSchema());
result.put("DataAnalysisSignificanceV1", new DataAnalysisSignificanceV1().toSchema());
result.put("DataAnalysisComparisonSideV1", new DataAnalysisComparisonSideV1().toSchema());
result.put("DataAnalysisComparisonValueV1", new DataAnalysisComparisonValueV1().toSchema());
result.put("DataAnalysisFieldComparisonV1", new DataAnalysisFieldComparisonV1().toSchema());
result.put("DataAnalysisCompareV1", new DataAnalysisCompareV1().toSchema());
result.put("DataAnalysisShiftBucketV1", new DataAnalysisShiftBucketV1().toSchema());
result.put("DataAnalysisShiftV1", new DataAnalysisShiftV1().toSchema());
result.put("DataAnalysisCorrelationCellV1", new DataAnalysisCorrelationCellV1().toSchema());
result.put("DataAnalysisCorrelationV1", new DataAnalysisCorrelationV1().toSchema());
result.put("DataAnalysisTrendLineV1", new DataAnalysisTrendLineV1().toSchema());
result.put("DataAnalysisScatterV1", new DataAnalysisScatterV1().toSchema());
result.put("DataAnalysisCrosstabCellV1", new DataAnalysisCrosstabCellV1().toSchema());
result.put("DataAnalysisCrosstabV1", new DataAnalysisCrosstabV1().toSchema());
return (result);
}
/*******************************************************************************
** Reuse the common metric, filter and chart contracts.
*******************************************************************************/
private static Schema ref(String name)
{
return (new Schema().withRef("#/components/schemas/" + name));
}
/*******************************************************************************
** CompareRequest version-one transport model.
*******************************************************************************/
public static class DataAnalysisCompareRequestV1 implements ToSchema
{
@OpenAPIDescription("Population A filter; null selects the whole permitted table.")
public QQueryFilter filterA;
@OpenAPIDescription("Population B filter; null selects the whole permitted table.")
public QQueryFilter filterB;
@OpenAPIDescription("Display name of population A; default A.")
public String labelA;
@OpenAPIDescription("Display name of population B; default B.")
public String labelB;
@OpenAPIDescription("Distinct FULL fields to analyze; correlation requires 2 to 12 numeric fields.")
public List<String> fields;
/*******************************************************************************
** Explicit references preserve the standalone OpenAPI fragment.
*******************************************************************************/
@Override
public Schema toSchema()
{
Map<String, Schema> properties = new LinkedHashMap<>();
properties.put("filterA", ref("QueryFilter").withDescription("Population A filter; null selects the whole permitted table.").withNullable(true));
properties.put("filterB", ref("QueryFilter").withDescription("Population B filter; null selects the whole permitted table.").withNullable(true));
properties.put("labelA", new Schema().withType(Type.STRING).withDescription("Display name of population A; default A."));
properties.put("labelB", new Schema().withType(Type.STRING).withDescription("Display name of population B; default B."));
properties.put("fields", new Schema().withType(Type.ARRAY).withItems(new Schema().withType(Type.STRING)).withDescription("Distinct FULL fields to analyze; correlation requires 2 to 12 numeric fields."));
return (new DataAnalysisSchemas.RequiredSchema(List.of("fields")).withType(Type.OBJECT).withProperties(properties));
}
}
/*******************************************************************************
** ShiftRequest version-one transport model.
*******************************************************************************/
public static class DataAnalysisShiftRequestV1 implements ToSchema
{
@OpenAPIDescription("Current-user query filter; record locks and core field rules apply.")
public QQueryFilter filter;
@OpenAPIDescription("FULL field whose distribution is compared over time.")
public String field;
@OpenAPIDescription("FULL DATE or DATE_TIME field for session-timezone calendar buckets.")
public String dateField;
@OpenAPIDescription("Calendar unit: HOUR, DAY, WEEK, MONTH, QUARTER or YEAR; default MONTH.")
public String bucket;
/*******************************************************************************
** Explicit references preserve the standalone OpenAPI fragment.
*******************************************************************************/
@Override
public Schema toSchema()
{
Map<String, Schema> properties = new LinkedHashMap<>();
properties.put("filter", ref("QueryFilter").withDescription("Current-user query filter; record locks and core field rules apply.").withNullable(true));
properties.put("field", new Schema().withType(Type.STRING).withDescription("FULL field whose distribution is compared over time."));
properties.put("dateField", new Schema().withType(Type.STRING).withDescription("FULL DATE or DATE_TIME field for session-timezone calendar buckets."));
properties.put("bucket", new Schema().withType(Type.STRING).withDescription("Calendar unit: HOUR, DAY, WEEK, MONTH, QUARTER or YEAR; default MONTH."));
return (new DataAnalysisSchemas.RequiredSchema(List.of("field", "dateField")).withType(Type.OBJECT).withProperties(properties));
}
}
/*******************************************************************************
** CorrelationRequest version-one transport model.
*******************************************************************************/
public static class DataAnalysisCorrelationRequestV1 implements ToSchema
{
@OpenAPIDescription("Current-user query filter; record locks and core field rules apply.")
public QQueryFilter filter;
@OpenAPIDescription("Distinct FULL fields to analyze; correlation requires 2 to 12 numeric fields.")
public List<String> fields;
/*******************************************************************************
** Explicit references preserve the standalone OpenAPI fragment.
*******************************************************************************/
@Override
public Schema toSchema()
{
Map<String, Schema> properties = new LinkedHashMap<>();
properties.put("filter", ref("QueryFilter").withDescription("Current-user query filter; record locks and core field rules apply.").withNullable(true));
properties.put("fields", new Schema().withType(Type.ARRAY).withItems(new Schema().withType(Type.STRING)).withDescription("Distinct FULL fields to analyze; correlation requires 2 to 12 numeric fields."));
return (new DataAnalysisSchemas.RequiredSchema(List.of("fields")).withType(Type.OBJECT).withProperties(properties));
}
}
/*******************************************************************************
** ScatterRequest version-one transport model.
*******************************************************************************/
public static class DataAnalysisScatterRequestV1 implements ToSchema
{
@OpenAPIDescription("Table for the scatter link; route parameter takes precedence.")
public String tableName;
@OpenAPIDescription("Compatibility flag; scatter always returns the bounded sample.")
public Boolean exact;
@OpenAPIDescription("Current-user query filter; record locks and core field rules apply.")
public QQueryFilter filter;
@OpenAPIDescription("FULL numeric field on the x axis.")
public String xField;
@OpenAPIDescription("FULL numeric field on the y axis.")
public String yField;
@OpenAPIDescription("Maximum sample points (1 to 2000, default 2000) or kept crosstab categories per axis (1 to 20, default 20).")
public Integer limit;
/*******************************************************************************
** Explicit references preserve the standalone OpenAPI fragment.
*******************************************************************************/
@Override
public Schema toSchema()
{
Map<String, Schema> properties = new LinkedHashMap<>();
properties.put("tableName", new Schema().withType(Type.STRING).withDescription("Table for the scatter link; route parameter takes precedence.").withNullable(true));
properties.put("exact", new Schema().withType(Type.BOOLEAN).withDescription("Compatibility flag; scatter always returns the bounded sample.").withNullable(true));
properties.put("filter", ref("QueryFilter").withDescription("Current-user query filter; record locks and core field rules apply.").withNullable(true));
properties.put("xField", new Schema().withType(Type.STRING).withDescription("FULL numeric field on the x axis."));
properties.put("yField", new Schema().withType(Type.STRING).withDescription("FULL numeric field on the y axis."));
properties.put("limit", new Schema().withType(Type.INTEGER).withDescription("Maximum sample points (1 to 2000, default 2000) or kept crosstab categories per axis (1 to 20, default 20)."));
return (new DataAnalysisSchemas.RequiredSchema(List.of("xField", "yField")).withType(Type.OBJECT).withProperties(properties));
}
}
/*******************************************************************************
** CrosstabRequest version-one transport model.
*******************************************************************************/
public static class DataAnalysisCrosstabRequestV1 implements ToSchema
{
@OpenAPIDescription("Current-user query filter; record locks and core field rules apply.")
public QQueryFilter filter;
@OpenAPIDescription("FULL field defining crosstab rows.")
public String rowField;
@OpenAPIDescription("FULL field defining crosstab columns.")
public String columnField;
@OpenAPIDescription("Maximum sample points (1 to 2000, default 2000) or kept crosstab categories per axis (1 to 20, default 20).")
public Integer limit;
/*******************************************************************************
** Explicit references preserve the standalone OpenAPI fragment.
*******************************************************************************/
@Override
public Schema toSchema()
{
Map<String, Schema> properties = new LinkedHashMap<>();
properties.put("filter", ref("QueryFilter").withDescription("Current-user query filter; record locks and core field rules apply.").withNullable(true));
properties.put("rowField", new Schema().withType(Type.STRING).withDescription("FULL field defining crosstab rows."));
properties.put("columnField", new Schema().withType(Type.STRING).withDescription("FULL field defining crosstab columns."));
properties.put("limit", new Schema().withType(Type.INTEGER).withDescription("Maximum sample points (1 to 2000, default 2000) or kept crosstab categories per axis (1 to 20, default 20)."));
return (new DataAnalysisSchemas.RequiredSchema(List.of("rowField", "columnField")).withType(Type.OBJECT).withProperties(properties));
}
}
/*******************************************************************************
** Significance version-one transport model.
*******************************************************************************/
public static class DataAnalysisSignificanceV1 implements ToSchema
{
@OpenAPIDescription("Test.")
public String test;
@OpenAPIDescription("Statistic.")
public Double statistic;
@OpenAPIDescription("Degrees of freedom; null when undefined.")
public Double df;
@OpenAPIDescription("Two-sided p-value; p >= 0.05 is never significant.")
public Double pValue;
@OpenAPIDescription("Whether all test validity and privacy requirements hold.")
public Boolean applicable;
@OpenAPIDescription("Plain-language result or reason the statistic is not applicable.")
public String sentence;
@OpenAPIDescription("Cramer association strength computed on the pooled contingency table; null when invalid.")
public Double cramersV;
/*******************************************************************************
** Explicit references preserve the standalone OpenAPI fragment.
*******************************************************************************/
@Override
public Schema toSchema()
{
Map<String, Schema> properties = new LinkedHashMap<>();
properties.put("test", new Schema().withType(Type.STRING).withDescription("Test.").withNullable(true));
properties.put("statistic", new Schema().withType(Type.NUMBER).withDescription("Statistic.").withNullable(true));
properties.put("df", new Schema().withType(Type.NUMBER).withDescription("Degrees of freedom; null when undefined.").withNullable(true));
properties.put("pValue", new Schema().withType(Type.NUMBER).withDescription("Two-sided p-value; p >= 0.05 is never significant.").withNullable(true));
properties.put("applicable", new Schema().withType(Type.BOOLEAN).withDescription("Whether all test validity and privacy requirements hold.").withNullable(true));
properties.put("sentence", new Schema().withType(Type.STRING).withDescription("Plain-language result or reason the statistic is not applicable.").withNullable(true));
properties.put("cramersV", new Schema().withType(Type.NUMBER).withDescription("Cramer association strength computed on the pooled contingency table; null when invalid.").withNullable(true));
return (new Schema().withType(Type.OBJECT).withProperties(properties));
}
}
/*******************************************************************************
** ComparisonSide version-one transport model.
*******************************************************************************/
public static class DataAnalysisComparisonSideV1 implements ToSchema
{
@OpenAPIDescription("Label.")
public String label;
@OpenAPIDescription("Typed metrics with exact population drills unless privacy suppresses them.")
public List<DataAnalysisSchemas.DataAnalysisMetricV1> metrics;
/*******************************************************************************
** Explicit references preserve the standalone OpenAPI fragment.
*******************************************************************************/
@Override
public Schema toSchema()
{
Map<String, Schema> properties = new LinkedHashMap<>();
properties.put("label", new Schema().withType(Type.STRING).withDescription("Label.").withNullable(true));
properties.put("metrics", new Schema().withType(Type.ARRAY).withItems(ref("DataAnalysisMetricV1")).withDescription("Typed metrics with exact population drills unless privacy suppresses them.").withNullable(true));
return (new Schema().withType(Type.OBJECT).withProperties(properties));
}
}
/*******************************************************************************
** ComparisonValue version-one transport model.
*******************************************************************************/
public static class DataAnalysisComparisonValueV1 implements ToSchema
{
@OpenAPIDescription("Value.")
public Serializable value;
@OpenAPIDescription("Label.")
public String label;
@OpenAPIDescription("Side a.")
public DataAnalysisComparisonSideV1 sideA;
@OpenAPIDescription("Side b.")
public DataAnalysisComparisonSideV1 sideB;
@OpenAPIDescription("B minus A, in original units (share differences are fractions).")
public DataAnalysisSchemas.DataAnalysisMetricV1 delta;
@OpenAPIDescription("(B minus A) divided by absolute A, a fraction; null at a zero baseline.")
public DataAnalysisSchemas.DataAnalysisMetricV1 percentDelta;
@OpenAPIDescription("Test assumptions, two-sided p-value, degrees of freedom and plain-language conclusion.")
public DataAnalysisSignificanceV1 significance;
/*******************************************************************************
** Explicit references preserve the standalone OpenAPI fragment.
*******************************************************************************/
@Override
public Schema toSchema()
{
Map<String, Schema> properties = new LinkedHashMap<>();
properties.put("value", new Schema().withDescription("Value.").withNullable(true));
properties.put("label", new Schema().withType(Type.STRING).withDescription("Label.").withNullable(true));
properties.put("sideA", ref("DataAnalysisComparisonSideV1").withDescription("Side a.").withNullable(true));
properties.put("sideB", ref("DataAnalysisComparisonSideV1").withDescription("Side b.").withNullable(true));
properties.put("delta", ref("DataAnalysisMetricV1").withDescription("B minus A, in original units (share differences are fractions).").withNullable(true));
properties.put("percentDelta", ref("DataAnalysisMetricV1").withDescription("(B minus A) divided by absolute A, a fraction; null at a zero baseline.").withNullable(true));
properties.put("significance", ref("DataAnalysisSignificanceV1").withDescription("Test assumptions, two-sided p-value, degrees of freedom and plain-language conclusion.").withNullable(true));
return (new Schema().withType(Type.OBJECT).withProperties(properties));
}
}
/*******************************************************************************
** FieldComparison version-one transport model.
*******************************************************************************/
public static class DataAnalysisFieldComparisonV1 implements ToSchema
{
@OpenAPIDescription("FULL field whose distribution is compared over time.")
public String field;
@OpenAPIDescription("Values.")
public List<DataAnalysisComparisonValueV1> values;
@OpenAPIDescription("Test assumptions, two-sided p-value, degrees of freedom and plain-language conclusion.")
public DataAnalysisSignificanceV1 significance;
@OpenAPIDescription("Semantic series; category comparisons are grouped and category time series are stacked.")
public DataAnalysisSchemas.DataAnalysisChartV1 chart;
/*******************************************************************************
** Explicit references preserve the standalone OpenAPI fragment.
*******************************************************************************/
@Override
public Schema toSchema()
{
Map<String, Schema> properties = new LinkedHashMap<>();
properties.put("field", new Schema().withType(Type.STRING).withDescription("FULL field whose distribution is compared over time.").withNullable(true));
properties.put("values", new Schema().withType(Type.ARRAY).withItems(ref("DataAnalysisComparisonValueV1")).withDescription("Values.").withNullable(true));
properties.put("significance", ref("DataAnalysisSignificanceV1").withDescription("Test assumptions, two-sided p-value, degrees of freedom and plain-language conclusion.").withNullable(true));
properties.put("chart", ref("DataAnalysisChartV1").withDescription("Semantic series; category comparisons are grouped and category time series are stacked.").withNullable(true));
return (new Schema().withType(Type.OBJECT).withProperties(properties));
}
}
/*******************************************************************************
** CompareResult version-one transport model.
*******************************************************************************/
public static class DataAnalysisCompareV1 implements ToSchema
{
@OpenAPIDescription("Distinct FULL fields to analyze; correlation requires 2 to 12 numeric fields.")
public List<DataAnalysisFieldComparisonV1> fields;
/*******************************************************************************
** Explicit references preserve the standalone OpenAPI fragment.
*******************************************************************************/
@Override
public Schema toSchema()
{
Map<String, Schema> properties = new LinkedHashMap<>();
properties.put("fields", new Schema().withType(Type.ARRAY).withItems(ref("DataAnalysisFieldComparisonV1")).withDescription("Distinct FULL fields to analyze; correlation requires 2 to 12 numeric fields.").withNullable(true));
return (new Schema().withType(Type.OBJECT).withProperties(properties));
}
}
/*******************************************************************************
** ShiftBucket version-one transport model.
*******************************************************************************/
public static class DataAnalysisShiftBucketV1 implements ToSchema
{
@OpenAPIDescription("Value.")
public Serializable value;
@OpenAPIDescription("Label.")
public String label;
@OpenAPIDescription("True when the calendar bucket end has passed in the session timezone.")
public Boolean complete;
@OpenAPIDescription("Typed metrics with exact population drills unless privacy suppresses them.")
public List<DataAnalysisSchemas.DataAnalysisMetricV1> metrics;
/*******************************************************************************
** Explicit references preserve the standalone OpenAPI fragment.
*******************************************************************************/
@Override
public Schema toSchema()
{
Map<String, Schema> properties = new LinkedHashMap<>();
properties.put("value", new Schema().withDescription("Value.").withNullable(true));
properties.put("label", new Schema().withType(Type.STRING).withDescription("Label.").withNullable(true));
properties.put("complete", new Schema().withType(Type.BOOLEAN).withDescription("True when the calendar bucket end has passed in the session timezone.").withNullable(true));
properties.put("metrics", new Schema().withType(Type.ARRAY).withItems(ref("DataAnalysisMetricV1")).withDescription("Typed metrics with exact population drills unless privacy suppresses them.").withNullable(true));
return (new Schema().withType(Type.OBJECT).withProperties(properties));
}
}
/*******************************************************************************
** ShiftResult version-one transport model.
*******************************************************************************/
public static class DataAnalysisShiftV1 implements ToSchema
{
@OpenAPIDescription("Buckets.")
public List<DataAnalysisShiftBucketV1> buckets;
@OpenAPIDescription("Population stability index, null when inapplicable; zero shares are floored at 0.000001.")
public DataAnalysisSchemas.DataAnalysisMetricV1 psi;
@OpenAPIDescription("Plain-language result or reason the statistic is not applicable.")
public String sentence;
@OpenAPIDescription("Semantic series; category comparisons are grouped and category time series are stacked.")
public DataAnalysisSchemas.DataAnalysisChartV1 chart;
/*******************************************************************************
** Explicit references preserve the standalone OpenAPI fragment.
*******************************************************************************/
@Override
public Schema toSchema()
{
Map<String, Schema> properties = new LinkedHashMap<>();
properties.put("buckets", new Schema().withType(Type.ARRAY).withItems(ref("DataAnalysisShiftBucketV1")).withDescription("Buckets.").withNullable(true));
properties.put("psi", ref("DataAnalysisMetricV1").withDescription("Population stability index, null when inapplicable; zero shares are floored at 0.000001.").withNullable(true));
properties.put("sentence", new Schema().withType(Type.STRING).withDescription("Plain-language result or reason the statistic is not applicable.").withNullable(true));
properties.put("chart", ref("DataAnalysisChartV1").withDescription("Semantic series; category comparisons are grouped and category time series are stacked.").withNullable(true));
return (new Schema().withType(Type.OBJECT).withProperties(properties));
}
}
/*******************************************************************************
** CorrelationCell version-one transport model.
*******************************************************************************/
public static class DataAnalysisCorrelationCellV1 implements ToSchema
{
@OpenAPIDescription("FULL numeric field on the x axis.")
public String xField;
@OpenAPIDescription("FULL numeric field on the y axis.")
public String yField;
@OpenAPIDescription("Pairwise non-null population count; null when privacy suppresses it.")
public Long n;
@OpenAPIDescription("Pearson correlation; null for insufficient data, zero variance or privacy suppression.")
public Double r;
@OpenAPIDescription("POST the included parameters to the table scatter endpoint.")
public DataAnalysisScatterRequestV1 scatter;
/*******************************************************************************
** Explicit references preserve the standalone OpenAPI fragment.
*******************************************************************************/
@Override
public Schema toSchema()
{
Map<String, Schema> properties = new LinkedHashMap<>();
properties.put("xField", new Schema().withType(Type.STRING).withDescription("FULL numeric field on the x axis.").withNullable(true));
properties.put("yField", new Schema().withType(Type.STRING).withDescription("FULL numeric field on the y axis.").withNullable(true));
properties.put("n", new Schema().withType(Type.INTEGER).withDescription("Pairwise non-null population count; null when privacy suppresses it.").withNullable(true));
properties.put("r", new Schema().withType(Type.NUMBER).withDescription("Pearson correlation; null for insufficient data, zero variance or privacy suppression.").withNullable(true));
properties.put("scatter", ref("DataAnalysisScatterRequestV1").withDescription("POST the included parameters to the table scatter endpoint.").withNullable(true));
return (new Schema().withType(Type.OBJECT).withProperties(properties));
}
}
/*******************************************************************************
** CorrelationResult version-one transport model.
*******************************************************************************/
public static class DataAnalysisCorrelationV1 implements ToSchema
{
@OpenAPIDescription("Distinct FULL fields to analyze; correlation requires 2 to 12 numeric fields.")
public List<String> fields;
@OpenAPIDescription("Cells.")
public List<DataAnalysisCorrelationCellV1> cells;
@OpenAPIDescription("Semantic series; category comparisons are grouped and category time series are stacked.")
public DataAnalysisSchemas.DataAnalysisChartV1 chart;
/*******************************************************************************
** Explicit references preserve the standalone OpenAPI fragment.
*******************************************************************************/
@Override
public Schema toSchema()
{
Map<String, Schema> properties = new LinkedHashMap<>();
properties.put("fields", new Schema().withType(Type.ARRAY).withItems(new Schema().withType(Type.STRING)).withDescription("Distinct FULL fields to analyze; correlation requires 2 to 12 numeric fields.").withNullable(true));
properties.put("cells", new Schema().withType(Type.ARRAY).withItems(ref("DataAnalysisCorrelationCellV1")).withDescription("Cells.").withNullable(true));
properties.put("chart", ref("DataAnalysisChartV1").withDescription("Semantic series; category comparisons are grouped and category time series are stacked.").withNullable(true));
return (new Schema().withType(Type.OBJECT).withProperties(properties));
}
}
/*******************************************************************************
** TrendLine version-one transport model.
*******************************************************************************/
public static class DataAnalysisTrendLineV1 implements ToSchema
{
@OpenAPIDescription("Slope.")
public Double slope;
@OpenAPIDescription("Intercept.")
public Double intercept;
@OpenAPIDescription("Pearson correlation; null for insufficient data, zero variance or privacy suppression.")
public Double r;
/*******************************************************************************
** Explicit references preserve the standalone OpenAPI fragment.
*******************************************************************************/
@Override
public Schema toSchema()
{
Map<String, Schema> properties = new LinkedHashMap<>();
properties.put("slope", new Schema().withType(Type.NUMBER).withDescription("Slope.").withNullable(true));
properties.put("intercept", new Schema().withType(Type.NUMBER).withDescription("Intercept.").withNullable(true));
properties.put("r", new Schema().withType(Type.NUMBER).withDescription("Pearson correlation; null for insufficient data, zero variance or privacy suppression.").withNullable(true));
return (new Schema().withType(Type.OBJECT).withProperties(properties));
}
}
/*******************************************************************************
** ScatterResult version-one transport model.
*******************************************************************************/
public static class DataAnalysisScatterV1 implements ToSchema
{
@OpenAPIDescription("Pairwise non-null population count; null when privacy suppresses it.")
public Long n;
@OpenAPIDescription("Number of displayed paired records.")
public Integer sampleSize;
@OpenAPIDescription("Sampling method; core query currently uses a deterministic primary-key prefix.")
public String sampling;
@OpenAPIDescription("Points.")
public List<DataAnalysisSchemas.DataAnalysisPointV1> points;
@OpenAPIDescription("Least-squares slope, intercept and r fitted to the displayed sample.")
public DataAnalysisTrendLineV1 trend;
@OpenAPIDescription("Semantic series; category comparisons are grouped and category time series are stacked.")
public DataAnalysisSchemas.DataAnalysisChartV1 chart;
/*******************************************************************************
** Explicit references preserve the standalone OpenAPI fragment.
*******************************************************************************/
@Override
public Schema toSchema()
{
Map<String, Schema> properties = new LinkedHashMap<>();
properties.put("n", new Schema().withType(Type.INTEGER).withDescription("Pairwise non-null population count; null when privacy suppresses it.").withNullable(true));
properties.put("sampleSize", new Schema().withType(Type.INTEGER).withDescription("Number of displayed paired records.").withNullable(true));
properties.put("sampling", new Schema().withType(Type.STRING).withDescription("Sampling method; core query currently uses a deterministic primary-key prefix.").withNullable(true));
properties.put("points", new Schema().withType(Type.ARRAY).withItems(ref("DataAnalysisPointV1")).withDescription("Points.").withNullable(true));
properties.put("trend", ref("DataAnalysisTrendLineV1").withDescription("Least-squares slope, intercept and r fitted to the displayed sample.").withNullable(true));
properties.put("chart", ref("DataAnalysisChartV1").withDescription("Semantic series; category comparisons are grouped and category time series are stacked.").withNullable(true));
return (new Schema().withType(Type.OBJECT).withProperties(properties));
}
}
/*******************************************************************************
** CrosstabCell version-one transport model.
*******************************************************************************/
public static class DataAnalysisCrosstabCellV1 implements ToSchema
{
@OpenAPIDescription("Row index.")
public Integer rowIndex;
@OpenAPIDescription("Column index.")
public Integer columnIndex;
@OpenAPIDescription("Cell count with its exact drill, or a suppressed metric.")
public DataAnalysisSchemas.DataAnalysisMetricV1 count;
@OpenAPIDescription("Cell count divided by row total; suppressed if it could disclose a hidden cell.")
public DataAnalysisSchemas.DataAnalysisMetricV1 rowShare;
@OpenAPIDescription("Cell count divided by column total; suppressed if it could disclose a hidden cell.")
public DataAnalysisSchemas.DataAnalysisMetricV1 columnShare;
/*******************************************************************************
** Explicit references preserve the standalone OpenAPI fragment.
*******************************************************************************/
@Override
public Schema toSchema()
{
Map<String, Schema> properties = new LinkedHashMap<>();
properties.put("rowIndex", new Schema().withType(Type.INTEGER).withDescription("Row index.").withNullable(true));
properties.put("columnIndex", new Schema().withType(Type.INTEGER).withDescription("Column index.").withNullable(true));
properties.put("count", ref("DataAnalysisMetricV1").withDescription("Cell count with its exact drill, or a suppressed metric.").withNullable(true));
properties.put("rowShare", ref("DataAnalysisMetricV1").withDescription("Cell count divided by row total; suppressed if it could disclose a hidden cell.").withNullable(true));
properties.put("columnShare", ref("DataAnalysisMetricV1").withDescription("Cell count divided by column total; suppressed if it could disclose a hidden cell.").withNullable(true));
return (new Schema().withType(Type.OBJECT).withProperties(properties));
}
}
/*******************************************************************************
** CrosstabResult version-one transport model.
*******************************************************************************/
public static class DataAnalysisCrosstabV1 implements ToSchema
{
@OpenAPIDescription("Rows.")
public List<DataAnalysisSchemas.DataAnalysisPivotHeaderV1> rows;
@OpenAPIDescription("Columns.")
public List<DataAnalysisSchemas.DataAnalysisPivotHeaderV1> columns;
@OpenAPIDescription("Cells.")
public List<DataAnalysisCrosstabCellV1> cells;
@OpenAPIDescription("Test assumptions, two-sided p-value, degrees of freedom and plain-language conclusion.")
public DataAnalysisSignificanceV1 significance;
/*******************************************************************************
** Explicit references preserve the standalone OpenAPI fragment.
*******************************************************************************/
@Override
public Schema toSchema()
{
Map<String, Schema> properties = new LinkedHashMap<>();
properties.put("rows", new Schema().withType(Type.ARRAY).withItems(ref("DataAnalysisPivotHeaderV1")).withDescription("Rows.").withNullable(true));
properties.put("columns", new Schema().withType(Type.ARRAY).withItems(ref("DataAnalysisPivotHeaderV1")).withDescription("Columns.").withNullable(true));
properties.put("cells", new Schema().withType(Type.ARRAY).withItems(ref("DataAnalysisCrosstabCellV1")).withDescription("Cells.").withNullable(true));
properties.put("significance", ref("DataAnalysisSignificanceV1").withDescription("Test assumptions, two-sided p-value, degrees of freedom and plain-language conclusion.").withNullable(true));
return (new Schema().withType(Type.OBJECT).withProperties(properties));
}
}
}