11import { ref , computed } from 'vue' ;
22import { defineStore } from 'pinia' ;
3+ // import { parse, type ParseResult } from 'papaparse';
4+ import { loadCSV , agg , op , from , bin , rolling , escape , desc , type ColumnTable } from 'arquero' ;
5+ import { data } from 'autoprefixer' ;
36
47export const useDataPackageStore = defineStore ( 'dataPackageStore' , ( ) => {
58 const dataPackagePath = './data/hubmap_2025-05-05/datapackage_udi.json' ;
@@ -10,11 +13,102 @@ export const useDataPackageStore = defineStore('dataPackageStore', () => {
1013 . then ( ( response ) => response . json ( ) )
1114 . then ( ( json ) => {
1215 dataPackage . value = json ;
16+ initializeDataFieldDomains ( ) ;
1317 } )
1418 . catch ( ( error ) => {
1519 console . error ( 'Error loading data package:' , error ) ;
1620 } ) ;
1721
22+ interface DataFieldDomain {
23+ entity : string ;
24+ field : string ;
25+ domain : IntervalDomain | CategoricalDomain ;
26+ }
27+
28+ interface IntervalDomain {
29+ type : 'interval' ;
30+ min : number ;
31+ max : number ;
32+ }
33+
34+ interface CategoricalDomain {
35+ values : string [ ] ;
36+ }
37+
38+ const dataFieldDomains = ref < DataFieldDomain [ ] > ( [ ] ) ;
39+
40+ function initializeDataFieldDomains ( ) {
41+ console . log ( 'init thingy' ) ;
42+ if ( ! dataPackage . value || ! dataPackage . value . resources ) return ;
43+ const folderPath = dataPackage . value [ 'udi:path' ] ;
44+ for ( const resource of dataPackage . value . resources ) {
45+ const entityName = resource . name ;
46+ const dataPath = resource . path ;
47+ const fullPath = `${ folderPath } /${ dataPath } ` ;
48+ addDataDomains ( fullPath , entityName ) ;
49+ }
50+ return ;
51+ }
52+
53+ function getDomainForField ( entity : string , field : string ) : DataFieldDomain | undefined {
54+ return dataFieldDomains . value . find (
55+ ( domain ) => domain . entity === entity && domain . field === field ,
56+ ) ;
57+ }
58+
59+ interface ValidStatus {
60+ isValid : 'yes' | 'no' | 'unknown' ;
61+ }
62+
63+ function isValidIntervalFilter (
64+ entity : string ,
65+ field : string ,
66+ min : number ,
67+ max : number ,
68+ ) : ValidStatus {
69+ if ( ! dataPackage . value || ! dataPackage . value . resources ) {
70+ return { isValid : 'unknown' } ;
71+ }
72+ const domain = getDomainForField ( entity , field ) ;
73+ if ( ! domain ) {
74+ return { isValid : 'no' } ;
75+ }
76+ return { isValid : 'yes' } ;
77+ }
78+
79+ async function addDataDomains ( path : string , entity : string ) : Promise < void > {
80+ const table = await loadCSV ( path ) ;
81+
82+ // Get column names
83+ const cols = table . columnNames ( ) ;
84+
85+ // Build domain info
86+ const domains : DataFieldDomain [ ] = [ ] ;
87+
88+ for ( const col of cols ) {
89+ const series = table . array ( col ) ; // raw column values
90+ const isNumeric = series . every ( ( v ) => v == null || ! isNaN ( + v ) ) ;
91+
92+ if ( isNumeric ) {
93+ const stats = table
94+ . rollup ( {
95+ min : `(d) => op.min(d["${ col } "])` ,
96+ max : `(d) => op.max(d["${ col } "])` ,
97+ } )
98+ . objects ( ) [ 0 ] ;
99+ domains . push ( {
100+ entity,
101+ field : col ,
102+ type : 'interval' ,
103+ domain : { min : stats . min , max : stats . max } ,
104+ } ) ;
105+ }
106+ // TODO: handle categorical data
107+ }
108+ dataFieldDomains . value . push ( ...domains ) ;
109+ return ;
110+ }
111+
18112 function removeVestigialInfo ( data : object ) : object {
19113 // remove udi:overlapping_fields
20114 // for each resource.schema
@@ -65,5 +159,5 @@ export const useDataPackageStore = defineStore('dataPackageStore', () => {
65159 return fieldsMap ;
66160 } ) ;
67161
68- return { dataPackage, dataPackageString, sourceFields } ;
162+ return { dataPackage, dataPackageString, sourceFields, isValidIntervalFilter , getDomainForField } ;
69163} ) ;
0 commit comments