GithubHelp home page GithubHelp logo

gumuslab / clustergrammer Goto Github PK

View Code? Open in Web Editor NEW

This project forked from moromis/clustergrammer-gl

2.0 1.0 9.0 31.25 MB

WebGL Clustergrammer JavaScript Library

Home Page: https://ismms-himc.github.io/clustergrammer-gl/

License: MIT License

JavaScript 79.50% Python 0.47% TypeScript 19.24% CSS 0.16% HTML 0.63%

clustergrammer's Introduction

Clustergramer

NPM NPM code style: prettier TypeScript Join the chat at https://gitter.im/GumusLab/clustergrammer

About

Clustergrammer, Clustergrammer2, and Clustergrammer-GL are packages originally developed by the Human Immune Monitoring Center and Ma'ayan lab at the Icahn School of Medicine at Mount Sinai.

This work is now being continued by Gumus Lab, also at ISMMS, and the code is being updated and maintained so it can be used in genomics project that the Gumus Lab is working on.

The project lead is Kevin Ulrich, who can be contacted here.

The original documentation for Clustergrammer and all its associated projects is located here, though it mainly applies in terms of creating formatted data with Clustergrammer-PY and the desired format for the data for Javascript applications.

Contributions

Contributions are totally welcome -- there are two ways to contribute:

  1. Find an issue that you want to tackle and comment on it/submit a PR for it.
  2. If you find a bug with Clustergrammer or want to make an enhancement, please write an issue detailing the change and make sure the community is on board, and then submit a PR for the changes.

Setup for Local Development

  1. Make sure you have Node 16+ (ideally use LTS) -- see NVM for Node version management
  2. Clone the code to your local machine
  3. Run yarn to install all required node modules
  4. Run yarn start to build the package locally into the example/example-app folder and watch for changes (will rebuild automatically)
  5. Open a new terminal tab or window, cd example/example-app, run yarn to install all required node modules and then run yarn start to start the local test app
  6. Happy development! Everything should be kept in sync -- it is not quite hot reload though so you will have to refresh the webpage after you make changes to see them reflected.

Let me know if you have any ideas on how to make the Clustergrammer isntances update when the source code updates (right now the sources on the page update fine but it doesn't reflect in the UI)

Licensing

The original license still applies, and the code is MIT-licensed.

clustergrammer's People

Contributors

cornhundred avatar dependabot[bot] avatar gitter-badger avatar jozefsedlak103 avatar moromis avatar tschaka1904 avatar turhanberk avatar wenheli avatar

Stargazers

 avatar  avatar

Watchers

 avatar

clustergrammer's Issues

Swipe to pan

Right now the only way to pan the chart when zoomed in is to click and drag, but you should be able to two-finger swipe on a touchpad as well.

Tooltip freezes

Describe the bug
The tooltip freezes sometimes when zooming or changing from one type to another (such as from dendrogram to matrix cell)

Add label click handler/differentiate onclick

We need to have an onclick handler for labels, currently we only have an onclick handler for matrix cells.

We could also just keep only the current onclick and return different information (consistency would be key if possible) depending on where the cursor is (check state.tooltip.tooltip_type)

Either way we probably want these methods to return an object so the user doesn't have to guess at how many params are returned (could also use ...rest but a ret object seems fine).

Multiple instances of Clustergrammer have duplicate labels

If two Clustergrammer charts are rendered (with different or the same data), the labels from both will render on both, overlapping.

Screenshot:
image

Zooming in on one chart also causes the labels (though no other elements) of the other chart to zoom/distort

Screenshot:
image

Since this is only affecting the labels, one would think it might be related to the webworker label rendering added in #3 and #7 , but the webworker should be unused in Firefox since it isn't possible there, and the issues still exist in Firefox. This issue has likely existed for some time therefore, or at least since the initial project refactor.

Zooming in/out past max zoom causes unnecessary re-renders

Problem
If you zoom out, even if fully zoomed out, Clustergrammer will rerender for every zoom action (could be 10+ times if on a trackpad for instance). Most likely the same happens when fully zoomed in (untested)

Solution
Guard either zooming if trying to zoom in/out past max or guard re-rendering based on a zoom action if trying to zoom past max. Make sure you don't accidentally keep a switch from being reset or something like that if going for the second solution.

Label Loading Placeholder

After landing #3, the framework can load and generate labels asynchronously.
Therefore, we need to take care of a placeholder right now.
The proposed solution is:

  1. Add a new state/event indicate the loading/generating stage of the label.
  2. In this stage, the framework should render or display a placeholder.
  3. We might also want to allow a callback/hook to be passed, in case, users need to do customization.

Matrix cells reset on zoom/reorder

Describe the bug
Matrix cells reset to the original ordering/clustering (clust/clust for row/col) if you zoom after reordering/reclustering.

To Reproduce
Steps to reproduce the behavior:

  1. Select a new ordering, such as "sum"
  2. After the heatmap finishes reordering, zoom in -- the matrix cells will reset to their original view

Also:

  1. Change column ordering to "sum"
  2. Change ordering again, say to var
  3. The matrix cells will start from a clust/clust ordering instead of the sum/clust ordering.

Chart legend

Add chart legend, which should be a gradient on the right of the chart and should show the min and max values and the color that corresponds to each in a vertical legend.

Should look like:
image

Add options to set legend placement

Currently the legend is fixed in where it displays. This feature intends to add a parameter to Clustergrammer called legendOptions which would allow the user to change things like whether it's horizontal or vertical, min-max or max-min, and where the legend is positioned. Other options can be planned as comments on this issue.

(originally suggested by @WenheLI here)

Bug: Fix sorting on clicked label

When double clicking a label, it is supposed to order the row/col by its value. Currently this is not the case, as the sorting indices seem to be a little off.

Default (on load):
Screenshot 2022-10-21 at 13 40 31

Current behaviour on label sort:
Screenshot 2022-10-21 at 13 41 43

Wanted behaviour on label sort:
Screenshot 2022-10-21 at 13 40 18

Reducers - handle state gracefully

There are a bunch of reducers under src/state/reducers. Whilst they seem to be working fine, they don't seem to align with the redux/react docs entirely.

There are 3 areas where improvement could be done:

  1. Remove unnecessary state = * assignment. We shouldn't mutate the state.
  2. _.merge mutates the state. It should be merge({}, state, action.payload) (Caution: This is rather expensive. Maybe immutable-ops#deepMerge is an option)
  3. Remove unnecessary return state, as the reducer takes care of it. Only in cases where we want action.payload to replace the state we should return action.payload.

Further thoughts:
Maybe, the reducers could be a little more detailed. Just to avoid to have to deal with functionalities like _.merge. If we would know where the change needs to be applied, we could probably get rid of the merge functionality. This would help the state (and any re-render).

Fix label clicking

Right now, if zoomed fully in, the top couple labels do not register via singleClicking, in this screenshot:
image
The first label you can click on the y-axis is DEF vs GHI

Fix typings for store

In adding namespaced redux store behavior to make multiple instances of Clustergrammer work on the same page, typings were broken. There's a few issues which concern this interface in store.ts

export interface NamespacedStore extends Store {
  actions: any;
  select: (path: string | string[]) => any;
  selectAll: () => Record<SliceNames, any>;
}

Typings for select and selectAll

  • selectAll should be easy since right now it's returning Record<SliceNames, any> and we just need to replace any with RootState
  • select can probably just replace string with SliceNames? It's unlikely that we can fix string[] and don't really use it anyways. It also needs to return a better type than any, maybe Partial<RootState> or something else that will at least get us going on type hints?

Typings for actions
This is a big one and I'm not exactly sure how to go about it. We'll probably have to rewrite all our slices in this way:

- import { createSlice, PayloadAction } from "@reduxjs/toolkit";
+ import {
+   createSlice,
+   PayloadAction,
+   SliceCaseReducers,
+   ValidateSliceCaseReducers,
+ } from "@reduxjs/toolkit";
import { merge } from "lodash";
+ import { RootState } from "../store/store";

export interface ArrsState {
  opacity_arr: any[];
  position_arr: {
    ini: any[][];
    new: any[][];
  };
}

const initialState: ArrsState = {} as ArrsState;

+ const reducers = {
+  setArrsState: (state: RootState, action: PayloadAction<ArrsState>) => {
+    state = action.payload;
+    return state;
+  },
+  mutateArrsState: (state: RootState, action: PayloadAction<Partial<ArrsState>>) => {
+    state = merge(state, action.payload);
+    return state;
+  },
+};

+ export type ArrsActions = keyof typeof reducers; // THIS IS THE IMPORTANT BIT

export const arrsSlice = (id: string) =>
  createSlice({
    name: `${id}_arrs`,
    initialState,
    // The `reducers` field lets us define reducers and generate associated actions
+   reducers: reducers as ValidateSliceCaseReducers<
+      ArrsState,
+      SliceCaseReducers<ArrsState>
+   >,
-    reducers: {
-      setArrsState: (state, action: PayloadAction<ArrsState>) => {
-        state = action.payload;
-        return state;
-      },
-      mutateArrsState: (state, action: PayloadAction<Partial<ArrsState>>) => {
-        state = merge(state, action.payload);
-        return state;
-      },
-    },
  });

And then doing a union of all the actions types as the type of actions.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.