Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cube projections (fixel) #33

Merged
merged 4 commits into from
Aug 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions plot/cube/cube.view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ namespace $.$$ {

@ $mol_mem
heatmap() {
if( this.multi_jsons() ) return false
return this.json().payload.points.v.some(val => Math.floor(val) !== val)
}

Expand Down
8 changes: 3 additions & 5 deletions plot/matrix/matrix.view.tree
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ $mpds_visavis_plot_matrix $mol_view
json_master null
show_setup true
size? 0
links_value_min? 0
links_value_max? 0
heatmap? false
heatmap false
matrix /
order /number
x_sort? \nump
Expand Down Expand Up @@ -56,10 +54,10 @@ $mpds_visavis_plot_matrix $mol_view
sub /
<= Heatmap_legend $mol_list
rows <= heatmap_color_list /
<= Heatmap_min $mol_view sub / <= links_value_min
<= Heatmap_min $mol_view sub / <= value_min 0
<= Heatmap_color*0 $mol_view
style * background <= heatmap_color* \
<= Heatmap_max $mol_view sub / <= links_value_max
<= Heatmap_max $mol_view sub / <= value_max 0
<= Setup $mol_view
sub <= setup /
<= Fixel $mol_check_box
Expand Down
162 changes: 108 additions & 54 deletions plot/matrix/matrix.view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ namespace $.$$ {
cmt: string
cmp: number
nonformer: boolean
intersection?: number
}

type Prop_name = keyof ReturnType<typeof $mpds_visavis_elements_list.prop_names>
Expand Down Expand Up @@ -125,41 +126,95 @@ namespace $.$$ {

@ $mol_mem
links() {
return this.json_master().payload.links.slice().sort( (a, b) => a.value - b.value )
return this.json_master().payload.links
}

@ $mol_mem
links_map() {
const map = new Map< string, typeof $mpds_visavis_plot_matrix_json_link['Value'][] >()
links_traversed() {
const links_map = new Map< string, typeof $mpds_visavis_plot_matrix_json_link['Value'][] >()
const cells_map = new Map< string, Matrix_cell >()
const heatmap_datasets: Set< number > = new Set
let value_min = Infinity
let value_max = -Infinity
const intersected_cells: Matrix_cell[] = []

this.links().forEach( l => {
map.get( l.cmt )?.push( l ) ?? map.set( l.cmt, [ l ] )
links_map.get( l.cmt )?.push( l ) ?? links_map.set( l.cmt, [ l ] )

const intersection = links_map.get( l.cmt )?.length ?? 0
if( intersection > 1 ) {
const cell = cells_map.get( l.cmt )!
cell.z += l.value
cell.intersection = intersection
intersected_cells.push( cell )
} else {
cells_map.set( l.cmt, {
y: l.source, x: l.target, cmt: l.cmt, cmp: l.cmp || 0, z: l.value, nonformer: false,
} )
}

if( Math.floor(l.value) !== l.value ) heatmap_datasets.add( l.cmp || 0 )

value_min = Math.min( value_min, l.value )
value_max = Math.max( value_max, l.value )
} )

return map
let intersect_value_min = Infinity
let intersect_value_max = -Infinity
if( heatmap_datasets.size == 2 ) {
intersected_cells.forEach( cell => {
const links = links_map.get( cell.cmt )!
cell.z = Math.abs( links[0].value - links[1].value )
intersect_value_min = Math.min( intersect_value_min, cell.z )
intersect_value_max = Math.max( intersect_value_max, cell.z )
} )
}

return { map: links_map, cells_map, heatmap_datasets, value_min, value_max, intersect_value_min, intersect_value_max }
}

@ $mol_mem_key
intersection_label( cmt: string ): string {
const quantity = this.links_map().get( cmt )?.length!
return quantity > 1 ? String( quantity ) : ''
@ $mol_mem
links_map() {
return this.links_traversed().map
}

@ $mol_mem
heatmap_datasets() {
return this.links_traversed().heatmap_datasets
}

links_value_min() {
return this.links()[0].value
@ $mol_mem
value_min() {
if( this.intersection_only() ) return this.links_traversed().intersect_value_min
return this.links_traversed().value_min
}

@ $mol_mem
value_max() {
if( this.intersection_only() ) return this.links_traversed().intersect_value_max
return this.links_traversed().value_max
}

links_value_max() {
return this.links().slice(-1)[0].value
@ $mol_mem
datasets_type() {
const heatmap_datasets = this.heatmap_datasets()
if( heatmap_datasets.size == 0 ) {
return 'entries'
}

const datesets_quantity = this.multi_jsons().length
if( datesets_quantity == 2 && heatmap_datasets.size == 2 ) {
return 'heatmap'
}

return 'mix'
}

@ $mol_mem
heatmap() {
return this.links().reduce( (heatmap, link) => {
if (!heatmap && Math.floor(link.value) !== link.value) return true
else if (link.cmp) return false
return heatmap
}, false )
if( this.datasets_type() != 'heatmap' ) return false
if( this.heatmap_datasets().size == 2 ) return this.intersection_only() ? true : false
return true
}

@ $mol_mem_key
Expand All @@ -178,18 +233,14 @@ namespace $.$$ {
matrix() {
const matrix: Matrix_cell[][] = this.nodes().map( (node, i) => {
return d3.range(95).map( (j: any) =>
({ x: j, y: i, z: 0, cmt: '', cmp: 0, nonformer: false })
({ x: j, y: i, z: 0, cmt: '', nonformer: false })
)
} )

for (const link of this.links()) {
matrix[link.source][link.target].z += link.value;
matrix[link.target][link.source].z += link.value; // NB only AB-all
matrix[link.source][link.target].cmt = link.cmt;
matrix[link.target][link.source].cmt = link.cmt; // NB only AB-all
matrix[link.source][link.target].cmp = link.cmp || 0;
matrix[link.target][link.source].cmp = link.cmp || 0;
}
this.links_traversed().cells_map.forEach( cell => {
matrix[cell.y][cell.x] = cell
matrix[cell.x][cell.y] = {...cell, x: cell.y, y: cell.x} // NB only AB-all
})

if (this.nonformers_checked()) {
for (const item of $mpds_visavis_elements_nonformer.pd_bin()) {
Expand All @@ -216,10 +267,11 @@ namespace $.$$ {
@ $mol_mem
opacity_scale() {
// return d3.scaleLinear().domain([this.links_value_min(), this.links_value_max()]).range([0.2, 1]).clamp(true) // for new d3 version
return d3.scale.linear().domain([this.links_value_min(), this.links_value_max()]).range([0.2, 1]).clamp(true)
return d3.scale.linear().domain([this.value_min(), this.value_max()]).range([0.2, 1]).clamp(true)
}

opacity(index: number) {
if( this.datasets_type() == 'mix' ) return 1
return this.heatmap() ? 1 : this.opacity_scale()(index)
}

Expand All @@ -244,11 +296,12 @@ namespace $.$$ {
@ $mol_mem
color_heatmap_scale() {
// return d3.scaleLinear().domain([this.links_value_min(), this.links_value_max()]).range([0, 1]) // for new d3 version
return d3.scale.linear().domain([this.links_value_min(), this.links_value_max()]).range([0, 1])
return d3.scale.linear().domain([this.value_min(), this.value_max()]).range([0, 1])
}

color(index: number, cmp: number) {
if (this.heatmap()) return cmp ? this.colorset()[1] : this.color_heatmap()( this.color_heatmap_scale()( index ) )
if (this.heatmap()) return this.color_heatmap()( this.color_heatmap_scale()( index ) )
// if (this.heatmap()) return cmp ? this.colorset()[1] : this.color_heatmap()( this.color_heatmap_scale()( index ) )
return this.colorset()[cmp] || '#ccc'
}

Expand All @@ -260,32 +313,38 @@ namespace $.$$ {

svg_title_text(cell: Matrix_cell) {
if (!cell.cmt) return ''
if( this.datasets_type() == 'mix' ) return cell.cmt

const text = `${cell.cmt}: ${cell.z}`
if( this.heatmap_datasets().has( Number(cell.cmt) || 0 ) ) return text

if( this.heatmap() ) return text

const links = this.links_map().get( cell.cmt )
const title = `${text} ${cell.z === 1 ? 'entry' : 'entries'}`

if( links?.length == 1 ) return title
const links = this.links_map().get( cell.cmt )
if( links?.length == 1 ) {
return title
}

return `${title} (${ links?.map( l => this.cmp_labels()[ l.cmp ?? 0 ] ).join('; ') })`
}

@ $mol_action
draw_cells(row_node: SVGElement, cells: Matrix_cell[], intersection_only: boolean) {
draw_row_cells( row_node: SVGElement, cells: Matrix_cell[], intersection_only: boolean ) {
const that = this

const range = this.range()
const rangeBand = range.rangeBand()

const enters = d3.select(row_node)
.selectAll('.cell')
.data(cells.filter(d => d.z && ( !intersection_only || that.intersection_label( d.cmt ) )))
.data( cells.filter( d => {
if( intersection_only ) return d.intersection ? true : false
if( d.z !== 0 || d.intersection ) return true
return false
} ) )
// .join('rect') // for new d3 version
.enter()

const rects = enters.append('rect')

rects.attr('class', (d: any) => d.nonformer ? 'nonformer cell' : 'cell')
Expand All @@ -296,12 +355,15 @@ namespace $.$$ {
.attr('width', rangeBand)
.attr('height', rangeBand)
.style('fill-opacity', (d: any) => this.opacity(d.z))
.style('fill', (d: any) => that.intersection_label( d.cmt ) ? 'gray' : this.color(d.z, d.cmp))
.style('fill', (d: any) => {
if( d.intersection && !that.heatmap() ) return 'gray'
return this.color(d.z ?? 1, d.cmp)
})

.on('mouseover', function (this: any, event: PointerEvent) {
const cell_data = d3.select(this).data()[0] as Matrix_cell
d3.select( that.dom_node_actual() ).selectAll( ".row text" ).classed( "active", (d: any, i: number)=> { return i == cell_data.y });
d3.select( that.dom_node_actual() ).selectAll( ".column text" ).classed( "active", (d: any, i: number)=> { return i == cell_data.x });
d3.select( that.dom_node_actual() ).selectAll( ".row .element" ).classed( "active", (d: any, i: number)=> i == cell_data.y )
d3.select( that.dom_node_actual() ).selectAll( ".column .element" ).classed( "active", (d: any, i: number)=> i == cell_data.x )
} )

.on('mouseout', function (this: any, event: PointerEvent) {
Expand All @@ -319,9 +381,10 @@ namespace $.$$ {
} )

rects.append('svg:title').text((cell: any) => this.svg_title_text(cell))
// .attr('mpds_visavis_plot_matrix_intersection', true)

enters.append('text')
.text((cell: any) => that.intersection_label(cell.cmt))
.text((cell: any) => cell.intersection || '')
.attr('x', (d: any) => range(d.x) + rangeBand / 2 )
.attr('dy', '.85em')
.attr('text-anchor', 'middle')
Expand Down Expand Up @@ -356,21 +419,21 @@ namespace $.$$ {
.attr('width', size)
.attr('height', size);

const draw_cells = (node: any, row: Matrix_cell[]) => this.draw_cells(node, row, this.intersection_only())

const that = this
const row = group.selectAll('.row')
.data(this.matrix())
// .join('g') // for new d3 version
.enter().append('g')
.attr('class', 'row')
.attr('transform', (d: any, i: number) => 'translate(0,' + this.range()(i as any) + ')' )
.each(function (this: any, cells: any) { draw_cells(this, cells) })
.each(function (this: any, cells: any) { that.draw_row_cells(this, cells, that.intersection_only()) })

row.append('line')
.attr('x2', size);

if( !this.y_op() ) {
row.append('text')
.attr('class', 'element')
.attr('x', -6)
// .attr('y', this.range().bandwidth() / 2) // for new d3 version
.attr('y', rangeBand / 2)
Expand All @@ -391,6 +454,7 @@ namespace $.$$ {

if( !this.x_op() ) {
column.append('text')
.attr('class', 'element')
.attr('x', 6)
// .attr('y', this.range().bandwidth() / 2) // for new d3 version
.attr('y', rangeBand / 2)
Expand Down Expand Up @@ -524,16 +588,6 @@ namespace $.$$ {
d3.selectAll("g.row text").classed("hidden", y_op);
d3.select("rect.bgmatrix").classed("hidden", (x_op || y_op));

// if (x_op){
// document.getElementById('matrix_xtitle').innerHTML = x_op + '/' + visavis.elemental_names[x_sort] + ' &rarr;';
// document.getElementById('matrix_xtitle').style.display = 'block';
// } else document.getElementById('matrix_xtitle').style.display = 'none';

// if (y_op){
// document.getElementById('matrix_ytitle').innerHTML = y_op + '/' + visavis.elemental_names[y_sort] + ' &rarr;';
// document.getElementById('matrix_ytitle').style.display = 'block';
// } else document.getElementById('matrix_ytitle').style.display = 'none';

var t = svg.transition().duration(600);

if (y_op){
Expand Down
Loading
Loading