Skip to content

Commit

Permalink
Thchang/profile smoothing (#986)
Browse files Browse the repository at this point in the history
* Prototype of Gaussian smoothing by GSL

* modify GSL building file

* Prototype of Gaussian smoothing with fixed kernel in spectral profiler

* Smoothing Profile: added Boxcar method and Kernel options

* added Smoothing panel

* modify smoothing kernel size option

* Added Hanning Smoothing in Spectral Profiler

* modified Boxcar/Gaussian Smoothing

* fix boxcar smoothing NaN value

* Modified gsl vector

* modified boxcar smoothing method

* modified boxcar smoothing method

* adjusted GSL build process and converted wrapper to C++

* updated lib and wrapper build scripts to use shared install directory

* Improved GSL WebAssambly memory management

* Added smoothing line color picker and overlay toggle

* Modified color, width and type of smoothing setting

* Added Decimation of profile smoothing

* minor modification of decimation smoothing

* Modified GSL lib building host from wasm32 to x86 in Emscripten

* Remove host setting in GLS lib building script

* Modified decimation method in profile smoothing

* Modified decimation method gsl implementation

* Added Binning in profile smoothin

* temp 0611 savitzky-golay

* Adjustment of plotdata method of smoothing data

* Modified Savitzkt-Golay method

* rename variables

* Modified the order of fitting polynomial in Savitzy-Golay

* change smoothing line default color

* Added exported data of profile smoothing, and revised plot components,

* Added ProfileSmoothingStore for applying smoothing in other profile widgets

* Added profile smoothing in Histogram and adjusted decimation method

* Added profile smoothing in spatial profiler

* Removed profile smoothing from histogram

* Added profile smoothing in stokes analysis

* Minor modification of stokes analysis

* Fixed decimation issue in spatial profiler and make minor modification

* Added host setting in gsl lib building script

* Modified GSL lib build script

* Adjusted GSL lib build scirpt

* Added endType controller for profile smoothing method with window function to handle edge value

* Modified GSL libs build script

* Improve local smoothing in spatial profiler

* add min/max parameters

* Minor adjustment

* Widen spatial settings widget

* remove smoothing endType

* update gsl lib build script

Co-authored-by: veggiesaurus <[email protected]>
  • Loading branch information
TienHao and veggiesaurus authored Jul 24, 2020
1 parent abac716 commit 0850b1c
Show file tree
Hide file tree
Showing 32 changed files with 1,246 additions and 178 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,11 @@ wasm_libs/zstd-1.4.4.tar.gz
wasm_src/carta_computation/build/*
wasm_src/carta_computation/post.js
public/carta_computation.wasm
# GSL
wasm_libs/gsl/*
wasm_libs/gsl-*.tar.gz
wasm_src/gsl_wrapper/build/*
public/gsl_wrapper.wasm

# Protocol buffers
protobuf/build/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,8 +304,7 @@ export class ContourDialogComponent extends React.Component {
xLabel: unitString,
darkMode: appStore.darkTheme,
logY: this.widgetStore.logScaleY,
usePointSymbols: this.widgetStore.plotType === PlotType.POINTS,
interpolateLines: this.widgetStore.plotType === PlotType.LINES,
plotType: this.widgetStore.plotType,
showYAxisTicks: false,
showYAxisLabel: false,
graphClicked: this.handleGraphClicked,
Expand Down
3 changes: 1 addition & 2 deletions src/components/Histogram/HistogramComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,7 @@ export class HistogramComponent extends React.Component<WidgetProps> {
imageName: imageName,
plotName: plotName,
logY: this.widgetStore.logScaleY,
usePointSymbols: this.widgetStore.plotType === PlotType.POINTS,
interpolateLines: this.widgetStore.plotType === PlotType.LINES,
plotType: this.widgetStore.plotType,
tickTypeY: TickType.Scientific,
graphZoomedX: this.widgetStore.setXBounds,
graphZoomedY: this.widgetStore.setYBounds,
Expand Down
3 changes: 1 addition & 2 deletions src/components/RenderConfig/RenderConfigComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,7 @@ export class RenderConfigComponent extends React.Component<WidgetProps> {
imageName: imageName,
plotName: plotName,
logY: this.widgetStore.logScaleY,
usePointSymbols: this.widgetStore.plotType === PlotType.POINTS,
interpolateLines: this.widgetStore.plotType === PlotType.LINES,
plotType: this.widgetStore.plotType,
showYAxisTicks: false,
showYAxisLabel: false,
graphClicked: this.onMinMoved,
Expand Down
39 changes: 24 additions & 15 deletions src/components/Shared/LinePlot/LinePlotComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ import {ChartArea} from "chart.js";
import {Scatter} from "react-chartjs-2";
import ReactResizeDetector from "react-resize-detector";
import {Arrow, Group, Layer, Line, Rect, Stage, Text} from "react-konva";
import {PlotContainerComponent, TickType} from "./PlotContainer/PlotContainerComponent";
import {PlotContainerComponent, TickType, MultiPlotProps} from "./PlotContainer/PlotContainerComponent";
import {ToolbarComponent} from "./Toolbar/ToolbarComponent";
import {StokesCoordinate} from "stores/widgets/StokesAnalysisWidgetStore";
import {Point2D} from "models";
import {clamp, toExponential} from "utilities";
import {PlotType} from "components/Shared";
import "./LinePlotComponent.css";

export enum ZoomMode {
Expand Down Expand Up @@ -60,10 +61,8 @@ export class LinePlotComponentProps {
darkMode?: boolean;
imageName?: string;
plotName?: string;
usePointSymbols?: boolean;
tickTypeX?: TickType;
tickTypeY?: TickType;
interpolateLines?: boolean;
markers?: LineMarker[];
showTopAxis?: boolean;
topAxisTickFormatter?: (value: number, index: number, values: number[]) => string | number;
Expand All @@ -75,7 +74,6 @@ export class LinePlotComponentProps {
graphZoomReset?: () => void;
graphCursorMoved?: (x: number) => void;
scrollZoom?: boolean;
multiPlotData?: Map<string, { x: number, y: number }[]>;
showXAxisTicks?: boolean;
showXAxisLabel?: boolean;
showYAxisTicks?: boolean;
Expand All @@ -84,8 +82,7 @@ export class LinePlotComponentProps {
yZeroLineColor?: string;
showLegend?: boolean;
xTickMarkLength?: number;
multiPlotBorderColor?: Map<string, string>;
plotType?: string;
plotType?: PlotType;
isGroupSubPlot?: boolean;
zIndex?: boolean;
pointRadius?: number;
Expand All @@ -94,6 +91,8 @@ export class LinePlotComponentProps {
multiColorSingleLineColors?: Array<string>;
multiColorMultiLinesColors?: Map<string, Array<string>>;
borderWidth?: number;
order?: number;
multiPlotPropsMap?: Map<string, MultiPlotProps>;
}

// Maximum time between double clicks
Expand Down Expand Up @@ -322,7 +321,7 @@ export class LinePlotComponent extends React.Component<LinePlotComponentProps> {
if (mouseMoveDist.x < DRAG_THRESHOLD && mouseMoveDist.y < DRAG_THRESHOLD) {
this.onStageClick(ev);
} else {
if (this.props.data || (this.props.multiPlotData && this.props.multiPlotData.size > 0)) {
if (this.props.data || (this.props.multiPlotPropsMap && this.props.multiPlotPropsMap.size > 0)) {
this.stageClickStartX = undefined;
this.stageClickStartY = undefined;
if (this.isSelecting && this.zoomMode !== ZoomMode.NONE) {
Expand Down Expand Up @@ -360,7 +359,7 @@ export class LinePlotComponent extends React.Component<LinePlotComponentProps> {
}

onStageMouseMove = (ev) => {
if (this.props.data || (this.props.multiPlotData && this.props.multiPlotData.size > 0)) {
if (this.props.data || (this.props.multiPlotPropsMap && this.props.multiPlotPropsMap.size > 0)) {
const mouseEvent: MouseEvent = ev.evt;
const chartArea = this.chartArea;
let mousePosX = clamp(mouseEvent.offsetX, chartArea.left - 1, chartArea.right + 1);
Expand Down Expand Up @@ -433,7 +432,7 @@ export class LinePlotComponent extends React.Component<LinePlotComponentProps> {
};

onStageWheel = (ev) => {
if ((this.props.data || (this.props.multiPlotData && this.props.multiPlotData.size > 0) ) && this.props.scrollZoom && this.props.graphZoomedX && this.chartArea) {
if ((this.props.data || (this.props.multiPlotPropsMap && this.props.multiPlotPropsMap.size > 0) ) && this.props.scrollZoom && this.props.graphZoomedX && this.chartArea) {
const wheelEvent: WheelEvent = ev.evt;
const chartArea = this.chartArea;
const lineHeight = 15;
Expand Down Expand Up @@ -557,15 +556,25 @@ export class LinePlotComponent extends React.Component<LinePlotComponentProps> {
} else {
rows = this.props.data.map(o => `${o.x}\t${toExponential(o.y, 10)}`);
}
} else if (this.props.multiPlotData && this.props.multiPlotData.size) {
this.props.multiPlotData.forEach((value, key) => {
}

if (this.props.multiPlotPropsMap && this.props.multiPlotPropsMap.size) {
this.props.multiPlotPropsMap.forEach((props, key) => {
if (key === StokesCoordinate.LinearPolarizationQ || key === StokesCoordinate.LinearPolarizationU) {
rows.push(`# ${key}\t`);
value.forEach(o => {
} else if (key.indexOf("smoothed") > -1) {
if (props.exportData) {
props.exportData.forEach((content, title) => {
rows.push(`# ${title}: ${content}\t`);
});
}
rows.push(`# smoothed_x\tsmoothed_y`);
}

if (props.data) {
props.data.forEach(o => {
rows.push(`${o.x}\t${toExponential(o.y, 10)}`);
});
} else {
rows = value.map(o => `${o.x}\t${toExponential(o.y, 10)}`);
}
});
}
Expand Down Expand Up @@ -849,7 +858,7 @@ export class LinePlotComponent extends React.Component<LinePlotComponentProps> {
}
<ToolbarComponent
darkMode={this.props.darkMode}
visible={this.isMouseEntered && (this.props.data !== undefined || (this.props.multiPlotData && this.props.multiPlotData.size > 0))}
visible={this.isMouseEntered && (this.props.data !== undefined || (this.props.multiPlotPropsMap && this.props.multiPlotPropsMap.size > 0))}
exportImage={this.exportImage}
exportData={this.exportData}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {ChartArea, ChartDataSets, ChartOptions} from "chart.js";
import {Scatter} from "react-chartjs-2";
import {Colors} from "@blueprintjs/core";
import {clamp, toExponential, toFixed} from "utilities";
import {PlotType} from "components/Shared";

export enum TickType {
Automatic,
Expand All @@ -26,15 +27,12 @@ export class PlotContainerProps {
lineColor?: string;
opacity?: number;
darkMode?: boolean;
usePointSymbols?: boolean;
tickTypeX?: TickType;
tickTypeY?: TickType;
interpolateLines?: boolean;
showTopAxis?: boolean;
topAxisTickFormatter?: (value: number, index: number, values: number[]) => string | number;
chartAreaUpdated?: (chartArea: ChartArea) => void;
plotRefUpdated?: (plotRef: Scatter) => void;
multiPlotData?: Map<string, { x: number, y: number }[]>;
showXAxisTicks?: boolean;
showXAxisLabel?: boolean;
showYAxisTicks?: boolean;
Expand All @@ -43,15 +41,26 @@ export class PlotContainerProps {
yZeroLineColor?: string;
showLegend?: boolean;
xTickMarkLength?: number;
multiPlotBorderColor?: Map<string, string>;
plotType?: string;
plotType?: PlotType;
dataBackgroundColor?: Array<string>;
isGroupSubPlot?: boolean;
pointRadius?: number;
zeroLineWidth?: number;
multiColorSingleLineColors?: Array<string>;
multiColorMultiLinesColors?: Map<string, Array<string>>;
borderWidth?: number;
order?: number;
multiPlotPropsMap?: Map<string, MultiPlotProps>;
}

export class MultiPlotProps {
data: { x: number, y: number }[];
type: PlotType;
borderColor?: string;
borderWidth?: number;
pointRadius?: number;
order?: number;
exportData?: Map<string, string>;
}

interface MulticolorLineChartDatasets extends ChartDataSets {
Expand Down Expand Up @@ -238,14 +247,10 @@ export class PlotContainerComponent extends React.Component<PlotContainerProps>
return true;
} else if (props.opacity !== nextProps.opacity) {
return true;
} else if (props.usePointSymbols !== nextProps.usePointSymbols) {
return true;
} else if (props.tickTypeX !== nextProps.tickTypeX) {
return true;
} else if (props.tickTypeY !== nextProps.tickTypeY) {
return true;
} else if (props.interpolateLines !== nextProps.interpolateLines) {
return true;
} else if (props.darkMode !== nextProps.darkMode) {
return true;
} else if (props.logY !== nextProps.logY) {
Expand Down Expand Up @@ -278,8 +283,6 @@ export class PlotContainerComponent extends React.Component<PlotContainerProps>
return true;
} else if (props.xTickMarkLength !== nextProps.xTickMarkLength) {
return true;
} else if (props.multiPlotBorderColor !== nextProps.multiPlotBorderColor) {
return true;
} else if (props.plotType !== nextProps.plotType) {
return true;
} else if (props.dataBackgroundColor !== nextProps.dataBackgroundColor) {
Expand Down Expand Up @@ -312,6 +315,12 @@ export class PlotContainerComponent extends React.Component<PlotContainerProps>
return true;
}
}

// Deep check of maps
if (!_.isEqual(props.multiPlotPropsMap, nextProps.multiPlotPropsMap)) {
return true;
}

// Skip any other changes
return false;
}
Expand Down Expand Up @@ -419,12 +428,13 @@ export class PlotContainerComponent extends React.Component<PlotContainerProps>
if (this.props.data && this.props.data.length) {
const datasetConfig: MulticolorLineChartDatasets = {
label: "LineGraph",
type: this.props.plotType ? this.props.plotType : "line",
type: "line",
data: this.props.data,
fill: false,
lineTension: 0,
order: this.props.order ? this.props.order : 0
};
if (this.props.usePointSymbols) {
if (this.props.plotType === PlotType.POINTS) {
datasetConfig.showLine = false;
datasetConfig.borderWidth = 0;
datasetConfig.borderColor = "rgba(0, 0, 0, 0)";
Expand All @@ -433,14 +443,14 @@ export class PlotContainerComponent extends React.Component<PlotContainerProps>
} else {
datasetConfig.pointRadius = 0;
datasetConfig.showLine = true;
datasetConfig.steppedLine = this.props.interpolateLines ? false : "middle";
datasetConfig.steppedLine = this.props.plotType === PlotType.STEPS ? "middle" : false;
datasetConfig.borderWidth = this.props.borderWidth ? this.props.borderWidth : 1;
datasetConfig.borderColor = lineColor;
}

// change line segments or points color with interaction
if (this.props.multiColorSingleLineColors && this.props.multiColorSingleLineColors.length) {
if (this.props.usePointSymbols) {
if (this.props.plotType === PlotType.POINTS) {
datasetConfig.pointBackgroundColor = this.props.multiColorSingleLineColors;
} else {
datasetConfig.pointRadius = 0.5;
Expand All @@ -456,23 +466,24 @@ export class PlotContainerComponent extends React.Component<PlotContainerProps>
plotData.push(datasetConfig);
}

if (this.props.multiPlotData) {
this.props.multiPlotData.forEach((value, key) => {
let currentLineColor = this.props.multiPlotBorderColor ? this.props.multiPlotBorderColor.get(key) : lineColor;
if (this.props.multiPlotPropsMap && this.props.multiPlotPropsMap.size > 0) {
this.props.multiPlotPropsMap.forEach((props, key) => {
let currentLineColor = props.borderColor ? props.borderColor : lineColor;
if (opacity < 1.0) {
currentLineColor = tinycolor(currentLineColor).setAlpha(opacity).toRgbString();
}
const multiPlotDatasetConfig: MulticolorLineChartDatasets = {
type: this.props.plotType ? this.props.plotType : "line",
label: key[0],
data: value,
type: "line",
label: key,
data: props.data,
fill: false,
lineTension: 0,
backgroundColor: currentLineColor,
order: props.order ? props.order : 0
};

if (this.props.multiColorMultiLinesColors && this.props.multiColorMultiLinesColors.size) {
if (this.props.usePointSymbols) {
if (props.type === PlotType.POINTS) {
multiPlotDatasetConfig.pointBackgroundColor = this.props.multiColorMultiLinesColors.get(key);
multiPlotDatasetConfig.borderColor = currentLineColor;
multiPlotDatasetConfig.pointBorderColor = "rgba(0, 0, 0, 0)";
Expand All @@ -481,19 +492,24 @@ export class PlotContainerComponent extends React.Component<PlotContainerProps>
}
}

if (this.props.usePointSymbols) {
let currentPointRadius = props.pointRadius ? props.pointRadius : this.props.pointRadius;
let currentLineWidth = props.borderWidth ? props.borderWidth : this.props.borderWidth;

if (props.type === PlotType.POINTS) {
multiPlotDatasetConfig.showLine = false;
multiPlotDatasetConfig.pointRadius = this.props.pointRadius ? this.props.pointRadius : 1;
multiPlotDatasetConfig.pointStyle = "circle";
multiPlotDatasetConfig.pointRadius = currentPointRadius ? currentPointRadius : 1;
multiPlotDatasetConfig.borderWidth = 0;
} else {
} else if (props.type === PlotType.LINES || props.type === PlotType.STEPS) {
multiPlotDatasetConfig.showLine = true;
multiPlotDatasetConfig.pointRadius = 0.5;
multiPlotDatasetConfig.pointStyle = "line";
multiPlotDatasetConfig.steppedLine = this.props.interpolateLines ? false : "middle";
multiPlotDatasetConfig.borderWidth = this.props.borderWidth ? this.props.borderWidth : 1;
multiPlotDatasetConfig.steppedLine = (props.type === PlotType.STEPS) ? "middle" : false;
multiPlotDatasetConfig.borderWidth = currentLineWidth ? currentLineWidth : 1;
multiPlotDatasetConfig.type = "multicolorLine";
multiPlotDatasetConfig.borderColor = currentLineColor;
}

plotData.push(multiPlotDatasetConfig);
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {NumericInput} from "@blueprintjs/core";

export class SafeNumericInput extends React.PureComponent<any> {
safeHandleValueChanged = (valueAsNumber: number, valueAsString: string) => {
if (this.props.onValueChange && isFinite(valueAsNumber)) {
if (this.props.onValueChange && isFinite(valueAsNumber) && (!this.props.min || this.props.min <= valueAsNumber) && (!this.props.max || this.props.max >= valueAsNumber)) {
this.props.onValueChange(valueAsNumber, valueAsString);
}
};
Expand Down
Loading

0 comments on commit 0850b1c

Please sign in to comment.