linnarsson-lab / loom-viewer

Tool for sharing, browsing and visualizing single-cell data stored in the Loom file format
BSD 2-Clause "Simplified" License
35 stars 6 forks source link

Make default value selection "smarter" #113

Closed JobLeonard closed 7 years ago

JobLeonard commented 7 years ago

So right now initial default values are hardcoded with an initialState object, and loaded in whenever the relevant view is opened for the first time:

const initialState = { // Initialise landscapeState for this dataset
    landscapeInitialized: true,
    col: {
        xAttrs: [{ attr: '_X', jitter: false, logscale: false }],
        yAttrs: [{ attr: '_Y', jitter: false, logscale: false }],
        colorAttr: 'Clusters',
        colorMode: 'Categorical',
        settings: {
            scaleFactor: 40,
            lowerBound: 0,
            upperBound: 100,
            log2Color: true,
            clip: false,
        },
    },
};

This works, _as long as _X, _Y, and Clusters exist in the Loom file_. For older files this is an issue. For example, some loom files have no Clusters attribute, but Class. This leads to views that require the user to manually search what attributes it does have to get a plot to show, which can be tiresome.

There are two ways to improve this:

const initialState = { // Initialise landscapeState for this dataset
    landscapeInitialized: true,
    col: {
        xAttrs: [{ 
            attr: findFirst(colAttrs, [ '_X', 'X', '_tSNE1', '_PCA1']), 
            jitter: false,
            logscale: false,
        }],
        yAttrs: [{
            attr: findFirst(colAttrs, [ '_Y', 'Y', '_tSNE2', '_PCA2']),
             jitter: false,
            logscale: false,
        }],
        colorAttr: attr: findFirst(colAttrs, [ 'Clusters', 'Class', '_KMeans_10']),
        colorMode: 'Categorical',
        settings: {
            scaleFactor: 40,
            lowerBound: 0,
            upperBound: 100,
            log2Color: true,
            clip: false,
        },
    },
};
JobLeonard commented 7 years ago

Huh... that was easy...

function returnFirstMatchingKey(obj, keyList){
    for (let i = 0; i < keyList.length; i++){
        if (obj[keyList[i]]) {
            return keyList[i];
        }
    }
    return '';
}