From 77d14ab3ae0d3f7bf34b695a5aad16e63380f832 Mon Sep 17 00:00:00 2001 From: gszep Date: Wed, 6 Oct 2021 16:40:22 +0100 Subject: [PATCH] dynamic colorbar limits --- Project.toml | 2 +- src/FlowAtlas.jl | 12 ++++++++---- src/assets/style.css | 1 - src/lib/colors.jl | 4 ++-- src/lib/map.jl | 3 --- src/lib/sidebar.jl | 11 ++++++++++- 6 files changed, 21 insertions(+), 12 deletions(-) diff --git a/Project.toml b/Project.toml index 9c53163..a2b1529 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "FlowAtlas" uuid = "ef7debb3-0d09-4604-8960-6109d4c5b3e0" authors = ["gszep "] -version = "0.1.6" +version = "0.1.7" [deps] CSVFiles = "5d742f6a-9f54-50ce-8119-2520741973ca" diff --git a/src/FlowAtlas.jl b/src/FlowAtlas.jl index 672603e..3470288 100644 --- a/src/FlowAtlas.jl +++ b/src/FlowAtlas.jl @@ -53,10 +53,12 @@ const extensions = JSServe.Dependency( :extensions, map( extension -> joinpath( function run( path::String; files::String=joinpath(dirname(path),"*.fcs"), transform::Function=x->asinh(x/250), port::Int = 3141, url::String = "http://localhost:$port", cols::Symbol=:union, drop::Union{Vector{String},Nothing}=String[], - nlevels::Int=10, channelRange = range(-3,7,length=50), channelScheme=reverse(ColorSchemes.matter), labelScheme=ColorSchemes.seaborn_colorblind, + nlevels::Int=10, nbins::Int=50, p::Real=0.1, channelScheme=reverse(ColorSchemes.matter), labelScheme=ColorSchemes.seaborn_colorblind, perplexity::Number=300, maxIter::Integer=10000, hold::Bool=true ) - indexTransform(x::AbstractVector{<:Union{Number,Missing}}) = toIndex(x, channelRange; nlevels=nlevels) + indexTransform(x::AbstractVector{<:Union{Number,Missing}}) = toIndex(x; nlevels=nlevels) + channelRange(x::AbstractVector{<:Union{Number,Missing}}) = range(quantile(skipmissing(x),(p,1-p))...,length=nlevels) + @info "Loading FCS files..." data, labels, groups, gating = FlowWorkspace.load( path; files=files, transform=transform, cols=cols) @@ -88,7 +90,7 @@ function run( path::String; files::String=joinpath(dirname(path),"*.fcs"), trans ), channels = ( - levels = range(extrema(channelRange)...,length=nlevels), + range = Dict([ col => channelRange(data[!,col]) for col ∈ Base.names(data) ]), rows = combine(data, [ col => indexTransform => col for col ∈ Base.names(data) ]), colors = channelview([map(x->RGBA(get(channelScheme, x)),range(0,1,length=nlevels)); RGBA(0,0,0,0)]), hex = map(x->'#'*hex(x),colorview(RGB,view(channelview(map(x->RGBA(get(channelScheme, x)),range(0,1,length=nlevels))),1:3,:))) @@ -96,6 +98,8 @@ function run( path::String; files::String=joinpath(dirname(path),"*.fcs"), trans ) ) + channelMin = minimum(map(col->minimum(skipmissing(data[!,col])),Base.names(data))) + channelMax = maximum(map(col->maximum(skipmissing(data[!,col])),Base.names(data))) for (name,color) ∈ colors.labels.names colors!( Dict(["name"=>name,"color"=>color]),labels,groups,colors) end ##################################################### initalise filter settings @@ -127,7 +131,7 @@ function run( path::String; files::String=joinpath(dirname(path),"*.fcs"), trans r"/\d+/\d+/\d+.png" => x->tile(x,embedding,selections,colors,names), r"/colors" => x->colors!(x,labels,groups,colors), r"/selection" => x->selection!(x,selections,names), - r"/gate" => x->gate(x,data,embedding,selections;channelRange=channelRange), + r"/gate" => x->gate(x,data,embedding,selections;channelRange=range(channelMin,channelMax,length=nbins)), r"/count" => x->count(x,selections), r"/favicon.ico" => context -> HTTP.Response(500), diff --git a/src/assets/style.css b/src/assets/style.css index 1ad923c..59065ed 100644 --- a/src/assets/style.css +++ b/src/assets/style.css @@ -117,7 +117,6 @@ top: 10; svg.colorbar { position: absolute; - visibility: hidden; z-index: 1; transform: translate(-50%,-50%); top: 50%; diff --git a/src/lib/colors.jl b/src/lib/colors.jl index 9d72c54..312c9e5 100644 --- a/src/lib/colors.jl +++ b/src/lib/colors.jl @@ -19,9 +19,9 @@ function colors!(label::Dict,labels::DataFrame,groups::DataFrame,colors::NamedTu return colors end -function toIndex(x::AbstractVector{<:Union{Number,Missing}},channelRange::AbstractVector{<:Number};nlevels::Int=10) +function toIndex(x::AbstractVector{<:Union{Number,Missing}};nlevels::Int=10,p::Real=0.1) - min,max = extrema(channelRange) + min,max = quantile(skipmissing(x),(p,1-p)) scaled = ( x .- min ) / ( max - min ) @. scaled[(scaled<0)&(~ismissing(scaled))] = 0 diff --git a/src/lib/map.jl b/src/lib/map.jl index 4181612..be7f3e9 100644 --- a/src/lib/map.jl +++ b/src/lib/map.jl @@ -4,9 +4,6 @@ function olMap(extrema::Array{<:Tuple}, colors::NamedTuple; port::Int = 3141) return js""" function (container){ - var colorScale = $d3.scaleLinear().domain($(colors.channels.levels)).range($(colors.channels.hex)) - $d3.select("#map").call( colorbar( colorScale, height=300, width=20, origin={x:40,y:10} )) - ////////////////////////////////////////////////// tile layer var projection = new $ol.proj.Projection({ code: 'raster', diff --git a/src/lib/sidebar.jl b/src/lib/sidebar.jl index 663b269..869914d 100644 --- a/src/lib/sidebar.jl +++ b/src/lib/sidebar.jl @@ -198,7 +198,16 @@ function sidebar(session::Session, names::NamedTuple, colors::NamedTuple; port:: "Colour by", DOM.select( DOM.option.(["Labels";names.channels]), id="channel", onchange = js""" - document.querySelector('svg.colorbar').style.visibility = document.getElementById('channel').value == 'Labels' ? 'hidden' : 'visible' + var channel = document.getElementById('channel').value + var channelRange = $(colors.channels.range) + + document.querySelector('svg.colorbar') ? document.querySelector('svg.colorbar').remove() : null + if (channel != 'Labels'){ + + var colorScale = $d3.scaleLinear().domain(channelRange[channel]).range($(colors.channels.hex)) + $d3.select("#map").call( colorbar( colorScale, height=300, width=20, origin={x:40,y:10} )) + } + document.getElementById("map").tiles.refresh() """) ),