1
1
import React , { useEffect , useContext , useState , useMemo } from 'react' ;
2
2
import {
3
- Button , H4 , H5 , Icon , Collapse , InputGroup , Text ,
3
+ Button , H4 , H5 , Icon , Collapse , InputGroup , Text , Switch ,
4
4
RangeSlider , Tag , HTMLSelect , Classes , Card , Elevation , Label
5
5
} from "@blueprintjs/core" ;
6
6
import { Popover2 , Tooltip2 } from "@blueprintjs/popover2" ;
@@ -40,6 +40,9 @@ const MarkerPlot = (props) => {
40
40
// records to show after filtering
41
41
const [ prosRecords , setProsRecords ] = useState ( null ) ;
42
42
43
+ // toggle for vs mode
44
+ const [ vsmode , setVsmode ] = useState ( false ) ;
45
+
43
46
// scale to use for detected on expression bar
44
47
const detectedScale = d3 . interpolateRdYlBu ; //d3.interpolateRdBu;
45
48
// d3.scaleSequential()
@@ -207,7 +210,7 @@ const MarkerPlot = (props) => {
207
210
</ Popover2 >
208
211
{
209
212
props ?. modality ?
210
- < Label style = { { textAlign : "left" } } >
213
+ < Label style = { { textAlign : "left" , marginBottom : "5px" } } >
211
214
Select Modality
212
215
< HTMLSelect
213
216
onChange = { ( x ) => {
@@ -223,30 +226,116 @@ const MarkerPlot = (props) => {
223
226
</ Label >
224
227
: ""
225
228
}
229
+ {
230
+ < div className = 'marker-cluster-header' >
231
+ < Label style = { { marginBottom :"0" } } > Select Cluster</ Label >
232
+ < div className = 'marker-vsmode' >
233
+ < Popover2
234
+ popoverClassName = { Classes . POPOVER_CONTENT_SIZING }
235
+ hasBackdrop = { false }
236
+ interactionKind = "hover"
237
+ placement = 'left'
238
+ hoverOpenDelay = { 500 }
239
+ modifiers = { {
240
+ arrow : { enabled : true } ,
241
+ flip : { enabled : true } ,
242
+ preventOverflow : { enabled : true } ,
243
+ } }
244
+ content = {
245
+ < Card style = { {
246
+ width : '450px'
247
+ } } elevation = { Elevation . ZERO }
248
+ >
249
+ < p >
250
+ By default, the < strong > general</ strong > mode will rank markers for a cluster or custom selection based on the comparison to all other clusters or cells.
251
+ < br /> < br /> Users can instead enable < strong > versus</ strong > mode to compare markers between two clusters or between two custom selections.
252
+ This is useful for identifying subtle differences between closely related groups of cells.
253
+ </ p >
254
+ </ Card >
255
+ }
256
+ >
257
+ < Icon intent = "warning" icon = "comparison" style = { { paddingRight : '5px' } } > </ Icon >
258
+ </ Popover2 >
259
+ < Switch large = { false } checked = { vsmode }
260
+ innerLabelChecked = "versus" innerLabel = "general"
261
+ onChange = { ( e ) => {
262
+ if ( e . target . checked === false ) {
263
+ props ?. setSelectedVSCluster ( null ) ;
264
+ }
265
+ setVsmode ( e . target . checked )
266
+ } } />
267
+ </ div >
268
+ </ div >
269
+ }
226
270
{
227
271
clusSel ?
228
- < Label style = { { textAlign : "left" } } >
229
- Select Cluster
230
- < HTMLSelect
231
- onChange = { ( x ) => {
232
- let tmpselection = x . currentTarget ?. value ;
233
- if ( tmpselection . startsWith ( "Cluster" ) ) {
234
- tmpselection = parseInt ( tmpselection . replace ( "Cluster " , "" ) ) - 1
235
- } else if ( tmpselection . startsWith ( "Custom" ) ) {
236
- tmpselection = tmpselection . replace ( "Custom Selection " , "" )
237
- }
238
- props ?. setSelectedCluster ( tmpselection ) ;
272
+ < div className = 'marker-cluster-selection' >
273
+ < HTMLSelect
274
+ className = 'marker-cluster-selection-width'
275
+ onChange = { ( x ) => {
276
+ let tmpselection = x . currentTarget ?. value ;
277
+ if ( tmpselection . startsWith ( "Cluster" ) ) {
278
+ tmpselection = parseInt ( tmpselection . replace ( "Cluster " , "" ) ) - 1
279
+ } else if ( tmpselection . startsWith ( "Custom" ) ) {
280
+ tmpselection = tmpselection . replace ( "Custom Selection " , "" )
281
+ }
282
+ props ?. setSelectedCluster ( tmpselection ) ;
283
+
284
+ setMarkerFilter ( { } ) ;
285
+ props ?. setGene ( null ) ;
286
+ props ?. setSelectedVSCluster ( null ) ;
287
+ } } >
288
+ {
289
+ clusSel . map ( ( x , i ) => (
290
+ < option
291
+ selected = { String ( props ?. selectedCluster ) . startsWith ( "cs" ) ? x == props ?. selectedCluster : parseInt ( x ) - 1 == parseInt ( props ?. selectedCluster ) }
292
+ key = { i } > { String ( x ) . startsWith ( "cs" ) ? "Custom Selection" : "Cluster" } { x } </ option >
293
+ ) )
294
+ }
295
+ </ HTMLSelect >
296
+ {
297
+ vsmode &&
298
+ < >
299
+ < Button style = { { margin : "0 3px" } } onClick = { ( ) => {
300
+ let mid = props ?. selectedVSCluster ;
301
+ props ?. setSelectedVSCluster ( props ?. selectedCluster )
302
+ props ?. setSelectedCluster ( mid ) ;
239
303
240
304
setMarkerFilter ( { } ) ;
241
305
props ?. setGene ( null ) ;
242
- } } >
243
- {
244
- clusSel . map ( ( x , i ) => (
245
- < option key = { i } > { String ( x ) . startsWith ( "cs" ) ? "Custom Selection" : "Cluster" } { x } </ option >
246
- ) )
247
- }
248
- </ HTMLSelect >
249
- </ Label >
306
+ } } icon = "exchange" disabled = { props ?. selectedVSCluster == null } outlined = { true } intent = "primary" > </ Button >
307
+ < HTMLSelect
308
+ className = 'marker-cluster-selection-width'
309
+ onChange = { ( x ) => {
310
+ let tmpselection = x . currentTarget ?. value ;
311
+ if ( tmpselection . startsWith ( "Cluster" ) ) {
312
+ tmpselection = parseInt ( tmpselection . replace ( "Cluster " , "" ) ) - 1
313
+ } else if ( tmpselection . startsWith ( "Custom" ) ) {
314
+ tmpselection = tmpselection . replace ( "Custom Selection " , "" )
315
+ }
316
+ props ?. setSelectedVSCluster ( tmpselection ) ;
317
+
318
+ setMarkerFilter ( { } ) ;
319
+ props ?. setGene ( null ) ;
320
+ } } >
321
+ {
322
+ props ?. selectedVSCluster == null && < option selected = { true } > Choose a Cluster</ option >
323
+ }
324
+ {
325
+ clusSel . filter ( ( x , i ) => String ( props ?. selectedCluster ) . startsWith ( "cs" ) ?
326
+ String ( x ) . startsWith ( "cs" ) && String ( x ) !== String ( props ?. selectedCluster ) :
327
+ ! String ( x ) . startsWith ( "cs" ) && parseInt ( x ) - 1 !== parseInt ( props ?. selectedCluster ) )
328
+ // .filter((x,i) => String(props?.selectedCluster) == String(x) )
329
+ . map ( ( x , i ) => (
330
+ < option
331
+ selected = { String ( props ?. selectedVSCluster ) . startsWith ( "cs" ) ? x == props ?. selectedVSCluster : parseInt ( x ) - 1 == parseInt ( props ?. selectedVSCluster ) }
332
+ key = { i } > { String ( x ) . startsWith ( "cs" ) ? "Custom Selection" : "Cluster" } { x } </ option >
333
+ ) )
334
+ }
335
+ </ HTMLSelect >
336
+ </ >
337
+ }
338
+ </ div >
250
339
: ""
251
340
}
252
341
{
0 commit comments