+ );
+ }
+}
+
+export default SliderConfig;
diff --git a/frontend/src/components/trackVis/CallingCardTrack.js b/frontend/src/components/trackVis/CallingCardTrack.js
index 51d5a2e1..f3709cee 100644
--- a/frontend/src/components/trackVis/CallingCardTrack.js
+++ b/frontend/src/components/trackVis/CallingCardTrack.js
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash';
-import { scaleLinear } from 'd3-scale';
+import { scaleLinear, scaleLog } from 'd3-scale';
import memoizeOne from 'memoize-one';
import { notify } from 'react-notify-toast';
import Track from './commonComponents/Track';
@@ -10,12 +10,18 @@ import GenomicCoordinates from './commonComponents/GenomicCoordinates';
import HoverTooltipContext from './commonComponents/tooltip/HoverTooltipContext';
import { RenderTypes, DesignRenderer } from '../../art/DesignRenderer';
import { ScaleChoices } from '../../model/ScaleChoices';
+import { LogChoices } from '../../model/LogChoices';
+import { DownsamplingChoices } from '../../model/DownsamplingChoices';
import { FeatureAggregator } from '../../model/FeatureAggregator';
export const DEFAULT_OPTIONS = {
height: 40,
color: "blue",
yScale: ScaleChoices.AUTO,
+ logScale: LogChoices.AUTO,
+ show: "all",
+ sampleSize: 1000,
+ opacity: [100],
yMax: 10,
yMin: 0,
markerSize: 3,
@@ -26,7 +32,7 @@ const TOP_PADDING = 5;
/**
* Track specialized in showing calling card data.
*
- * @author Silas Hsu and Daofeng Li
+ * @author Silas Hsu, Daofeng Li, and Arnav Moudgil
*/
class CallingCardTrack extends React.PureComponent {
static propTypes = Object.assign({}, Track.propsFromTrackContainer,
@@ -35,6 +41,11 @@ class CallingCardTrack extends React.PureComponent {
options: PropTypes.shape({
height: PropTypes.number.isRequired, // Height of the track
color: PropTypes.string, // Color to draw circle
+ scaleType: PropTypes.any, // Unused for now
+ scaleRange: PropTypes.array, // Unused for now
+ logScale: PropTypes.string, // For log-scaling y-axis
+ opacity: PropTypes.array, // For track opacity
+ show: PropTypes.string, // For downsampling
}).isRequired,
isLoading: PropTypes.bool, // If true, applies loading styling
error: PropTypes.any, // If present, applies error styling
@@ -44,7 +55,7 @@ class CallingCardTrack extends React.PureComponent {
super(props);
this.xToValue = null;
this.scales = null;
- this.computeScales = memoizeOne(this.computeScales);
+ // this.computeScales = memoizeOne(this.computeScales); // for some reason computeScales doesn't work when memoized
this.aggregateFeatures = memoizeOne(this.aggregateFeatures);
this.renderTooltip = this.renderTooltip.bind(this);
}
@@ -56,7 +67,7 @@ class CallingCardTrack extends React.PureComponent {
}
computeScales(xToValue, height) {
- const {yScale, yMin, yMax} = this.props.options;
+ const {yScale, yMin, yMax, logScale} = this.props.options;
if (yMin > yMax) {
notify.show('Y-axis min must less than max', 'error', 2000);
}
@@ -70,8 +81,23 @@ class CallingCardTrack extends React.PureComponent {
if (min > max) {
min = max;
}
+ // Define transformation function for log scaling
+ let transformer = null;
+ switch (logScale) {
+ case LogChoices.AUTO:
+ transformer = scaleLinear;
+ break;
+ case LogChoices.BASE10:
+ transformer = scaleLog;
+ // Set valid minimum value to one;
+ // after log-transforming, it will be zero
+ min = 1;
+ break;
+ default:
+ notify.show('Invalid logarithm base', 'error', 2000);
+ }
return {
- valueToY: scaleLinear().domain([max, min]).range([TOP_PADDING, height]).clamp(true),
+ valueToY: transformer().domain([max, min]).range([TOP_PADDING, height]).clamp(true),
min,
max,
};
@@ -81,48 +107,126 @@ class CallingCardTrack extends React.PureComponent {
* Renders the default tooltip that is displayed on hover.
*
* @param {number} relativeX - x coordinate of hover relative to the visualizer
+ * @param {number} relativeY - y coordinate of hover relative to the visualizer
* @param {number} value -
* @return {JSX.Element} tooltip to render
*/
- renderTooltip(relativeX) {
+ renderTooltip(relativeX, relativeY) {
const {trackModel, viewRegion, width} = this.props;
- const value = this.xToValue[Math.round(relativeX)];
- const stringValue = value !== undefined && value.length > 0 ? this.formatCards(value) : '(no data)';
- return (
-
-
-
-
-
{trackModel.getDisplayLabel()}
-
{stringValue}
-
- );
+ const {markerSize} = this.props.options;
+ // const radius = height * tooltipRadius;
+ var cards = [];
+ // Get nearest CallingCards to cursor along x-axis
+ for (let i = relativeX - markerSize; i <= relativeX + markerSize; i++) {
+ cards = cards.concat(this.xToValue[i]);
+ }
+ // Draw tooltip only if there are values near this x position
+ if (cards !== undefined && cards.length > 0) {
+ // Now find nearest CallingCards to the cursor along y-axis
+ const nearest = this.nearestCards(cards, relativeX, relativeY, markerSize);
+ if (nearest.length > 0) {
+ return (
+