@@ -377,8 +377,6 @@ SpectrumChartD3 = function(elem, options) {
377
377
. on ( "*.zoom" , null )
378
378
. on ( ".zoom" , null )
379
379
;
380
-
381
-
382
380
/// @TODO triggering the cancel events on document.body and window is probably a bit agressive; could probably do this for just this.vis + on leave events
383
381
d3 . select ( document . body )
384
382
. on ( "mouseup" , self . handleCancelAllMouseEvents ( ) )
@@ -538,6 +536,13 @@ SpectrumChartD3 = function(elem, options) {
538
536
539
537
if ( this . options . gridy )
540
538
this . setGridY ( this . options . gridy , true ) ;
539
+
540
+ this . vis . on ( "mouseout" , function ( ) {
541
+ if ( self . currentKineticRefLine ) {
542
+ self . currentKineticRefLine = null ;
543
+ self . drawRefGammaLines ( ) ;
544
+ }
545
+ } ) ;
541
546
}
542
547
543
548
registerKeyboardHandler = function ( callback ) {
@@ -1283,8 +1288,7 @@ SpectrumChartD3.prototype.setTitle = function(title,dontRedraw) {
1283
1288
. node ( ) . getBBox ( ) . height ;
1284
1289
this . options . txt . title = title ;
1285
1290
}
1286
- this . handleResize ( dontRedraw ) ;
1287
- this . refreshRefGammaLines ( ) ;
1291
+ this . handleResize ( dontRedraw ) ;
1288
1292
}
1289
1293
1290
1294
SpectrumChartD3 . prototype . hasCompactXAxis = function ( ) {
@@ -1730,14 +1734,15 @@ SpectrumChartD3.prototype.handleChartMouseMove = function() {
1730
1734
1731
1735
/* Right Click Dragging: pans the chart left and right */
1732
1736
self . handlePanChart ( ) ;
1733
- } else if ( self . options . allowDragRoiExtent
1734
- && self . rawData . spectra && self . rawData . spectra . length > 0
1737
+ } else if ( self . rawData . spectra && self . rawData . spectra . length > 0
1735
1738
&& ( x >= 0 && y >= 0 && y <= self . size . height && x <= self . size . width
1736
1739
&& ! d3 . event . altKey && ! d3 . event . ctrlKey && ! d3 . event . metaKey
1737
1740
&& ! d3 . event . shiftKey && ! self . fittingPeak && ! self . escapeKeyPressed ) ) {
1738
1741
// If we are here, the mouse button is not down, and the user isnt holding control, shift, etc
1739
-
1740
- if ( self . roiDragBoxes && self . showDragLineWhileInRoi && ! self . roiIsBeingDragged ) {
1742
+ if ( self . kineticRefLines )
1743
+ self . handleUpdateKineticRefLineUpdate ( ) ;
1744
+
1745
+ if ( self . options . allowDragRoiExtent && self . roiDragBoxes && self . showDragLineWhileInRoi && ! self . roiIsBeingDragged ) {
1741
1746
// If we're here, the user clicked on a peak to show the ROIS drag box/line, but the user
1742
1747
// hasnt moved mouse out of ROI, or clicked down, or hit esc or anything
1743
1748
const dx = ( self . showDragLineWhileInRoi ? 1 : 0.5 ) * self . options . roiDragWidth ;
@@ -1751,7 +1756,7 @@ SpectrumChartD3.prototype.handleChartMouseMove = function() {
1751
1756
1752
1757
if ( ! within_x )
1753
1758
self . handleCancelRoiDrag ( ) ;
1754
- } else if ( ! self . roiIsBeingDragged ) {
1759
+ } else if ( self . options . allowDragRoiExtent && ! self . roiIsBeingDragged ) {
1755
1760
1756
1761
//Also check if we are between ymin and ymax of ROI....
1757
1762
const drawn_roi = self . getDrawnRoiForCoordinate ( m , true ) ;
@@ -1812,15 +1817,17 @@ SpectrumChartD3.prototype.getMousePos = function(){
1812
1817
}
1813
1818
1814
1819
if ( this . lastMouseMovePos ) {
1815
- console . log ( 'getMousePos returning lastMouseMovePos (' , lastMouseMovePos , ")" )
1820
+ console . log ( 'getMousePos returning lastMouseMovePos (' , this . lastMouseMovePos , ")" )
1816
1821
return this . lastMouseMovePos ;
1817
1822
}
1818
1823
1819
- console . assert ( this . lastTapEvent , "Failed to find mouse position!" ) ;
1820
-
1821
1824
if ( this . lastTapEvent )
1822
1825
return this . lastTapEvent . visCoordinates ;
1823
1826
1827
+ //We can fail to get mouse position if a mouse/finger hasnt been over the chart yet
1828
+ //console.assert( this.lastTapEvent, "Failed to find mouse position!" );
1829
+ console . warn ( "Failed to find mouse position!" ) ;
1830
+
1824
1831
// I dont think we ever get here..., but I guess we'll just return _something_
1825
1832
return [ 0 , 0 , pad_left , pad_top ] ;
1826
1833
} //getMousePos(...)
@@ -2226,6 +2233,11 @@ SpectrumChartD3.prototype.handleChartMouseLeave = function() {
2226
2233
}
2227
2234
2228
2235
self . updateFeatureMarkers ( - 1 ) ;
2236
+
2237
+ if ( self . currentKineticRefLine ) {
2238
+ self . currentKineticRefLine = null ;
2239
+ self . drawRefGammaLines ( ) ;
2240
+ }
2229
2241
2230
2242
self . mousedOverRefLine = null ;
2231
2243
self . refLineInfo . style ( "display" , "none" ) ;
@@ -3994,7 +4006,8 @@ SpectrumChartD3.prototype.drawRefGammaLines = function() {
3994
4006
/*Drawing of the reference lines is super duper un-optimized!!! */
3995
4007
const self = this ;
3996
4008
3997
- if ( ! self . refLines || ! self . refLines . length || ! self . refLines [ 0 ] . lines || ! self . refLines [ 0 ] . lines . length ) {
4009
+ if ( ( ! self . refLines || ! self . refLines . length || ! self . refLines [ 0 ] . lines || ! self . refLines [ 0 ] . lines . length )
4010
+ && ( ! self . currentKineticRefLine || ! self . currentKineticRefLine . lines || ! self . currentKineticRefLine . lines . length ) ) {
3998
4011
self . vis . selectAll ( "g.ref" ) . remove ( ) ;
3999
4012
return ;
4000
4013
}
@@ -4006,14 +4019,20 @@ SpectrumChartD3.prototype.drawRefGammaLines = function() {
4006
4019
return lines . slice ( lindex , rindex ) . filter ( function ( d ) { return d . h > 1E-16 ; } ) ;
4007
4020
}
4008
4021
4009
- var lowerx = this . xScale . domain ( ) [ 0 ] , upperx = this . xScale . domain ( ) [ 1 ] ;
4022
+ let reflines = [ ] ;
4023
+ if ( self . refLines ) {
4024
+ self . refLines . forEach ( function ( input ) {
4025
+ const lines = getLinesInRange ( self . xScale . domain ( ) , input . lines ) ;
4026
+ input . maxVisibleAmp = d3 . max ( lines , function ( d ) { return d . h ; } ) ; /*same as lines[0].parent.maxVisibleAmp = ... */
4027
+ reflines = reflines . concat ( lines ) ;
4028
+ } ) ;
4029
+ }
4010
4030
4011
- var reflines = [ ] ;
4012
- self . refLines . forEach ( function ( input ) {
4013
- var lines = getLinesInRange ( self . xScale . domain ( ) , input . lines ) ;
4014
- input . maxVisibleAmp = d3 . max ( lines , function ( d ) { return d . h ; } ) ; /*same as lines[0].parent.maxVisibleAmp = ... */
4031
+ if ( self . currentKineticRefLine ) {
4032
+ const lines = getLinesInRange ( self . xScale . domain ( ) , self . currentKineticRefLine . lines ) ;
4033
+ self . currentKineticRefLine . maxVisibleAmp = d3 . max ( lines , function ( d ) { return d . h ; } ) ;
4015
4034
reflines = reflines . concat ( lines ) ;
4016
- } ) ;
4035
+ }
4017
4036
4018
4037
reflines . sort ( function ( l , r ) { return ( ( l . e < r . e ) ? - 1 : ( l . e === r . e ? 0 : 1 ) ) ; } ) ;
4019
4038
@@ -4023,10 +4042,6 @@ SpectrumChartD3.prototype.drawRefGammaLines = function() {
4023
4042
. attr ( "transform" , tx )
4024
4043
. attr ( "stroke-width" , self . options . refLineWidth ) ;
4025
4044
4026
- var gye = gy . enter ( ) . insert ( "g" , "a" )
4027
- . attr ( "class" , "ref" )
4028
- . attr ( "transform" , tx ) ;
4029
-
4030
4045
function stroke ( d ) { return d . color ? d . color : d . parent . color ; } ;
4031
4046
4032
4047
function dashfunc ( d ) {
@@ -4037,21 +4052,23 @@ SpectrumChartD3.prototype.drawRefGammaLines = function() {
4037
4052
return ( index > - 1 ) ? dash [ index ] : null ;
4038
4053
} ;
4039
4054
4040
- var h = self . size . height ;
4041
- var m = Math . min ( h , self . options . refLineTopPad ) ; // leave 20px margin at top of chart
4055
+ const h = self . size . height ;
4056
+ const m = Math . min ( h , self . options . refLineTopPad ) ; // leave 20px margin at top of chart
4042
4057
4043
- gye . append ( "line" )
4058
+ gy . enter ( ) . insert ( "g" , "a" )
4059
+ . attr ( "class" , "ref" )
4060
+ . attr ( "transform" , tx )
4061
+ . append ( "line" )
4044
4062
. style ( "stroke-dasharray" , dashfunc )
4045
4063
. attr ( "stroke" , stroke )
4046
4064
. attr ( "y1" , h )
4047
- . attr ( "dx" , "-0.5" )
4048
- ;
4065
+ . attr ( "dx" , "-0.5" ) ;
4049
4066
4050
4067
gy . exit ( ) . remove ( ) ; // Remove old elements as needed.
4051
4068
4052
- /* Now update the height of all the lines. If we did this in the gye. append("line") */
4053
- /* line above then the values for existing lines wouldnt be updated (only */
4054
- /* the new lines would have correct height) */
4069
+ /* Now update the height of all the lines. If we did this in the gy.enter(). append("line")
4070
+ line above then the values for existing lines wouldnt be updated (only
4071
+ the new lines would have correct height) */
4055
4072
const y2Lin = function ( d ) { return Math . min ( h - ( h - m ) * d . h / d . parent . maxVisibleAmp , h - 2 ) ; } ;
4056
4073
4057
4074
/*
@@ -4071,19 +4088,6 @@ SpectrumChartD3.prototype.drawRefGammaLines = function() {
4071
4088
. attr ( "y1" , h ) ; //needed for initial load sometimes
4072
4089
}
4073
4090
4074
- SpectrumChartD3 . prototype . refreshRefGammaLines = function ( ) {
4075
- var self = this ;
4076
-
4077
- // No need to clear, we don't have any data
4078
- if ( ! self . refLines )
4079
- return ;
4080
-
4081
- // Erase all the reference lines
4082
- self . vis . selectAll ( "g.ref" ) . remove ( ) ;
4083
-
4084
- // Redraw the reference gamma lines
4085
- self . drawRefGammaLines ( ) ;
4086
- }
4087
4091
4088
4092
SpectrumChartD3 . prototype . clearReferenceLines = function ( ) {
4089
4093
var self = this ;
@@ -4102,38 +4106,38 @@ SpectrumChartD3.prototype.setReferenceLines = function( data ) {
4102
4106
4103
4107
var default_colors = [ "#0000FF" , "#006600" , "#006666" , "#0099FF" , "#9933FF" , "#FF66FF" , "#CC3333" , "#FF6633" , "#FFFF99" , "#CCFFCC" , "#0000CC" , "#666666" , "#003333" ] ;
4104
4108
4105
- var index = 0 ;
4106
4109
if ( ! data ) {
4107
4110
this . refLines = null ;
4108
4111
} else {
4109
4112
try {
4110
4113
if ( ! Array . isArray ( data ) )
4111
4114
throw "Input is not an array of reference lines" ;
4112
4115
4113
- data . forEach ( function ( a , i ) {
4114
- if ( ! a . color )
4115
- a . color = default_colors [ i % default_colors . length ] ;
4116
- if ( ! a . lines || ! Array . isArray ( a . lines ) )
4117
- throw "Reference lines does not contain an array of lines" ;
4118
- a . lines . forEach ( function ( d ) {
4119
- d . id = ++ index ; //We need to assign an ID to use as D3 data, that is unique (energy may not be unique)
4120
-
4121
- /*{e:30.27,h:6.22e-05,particle:'xray',decay:'xray',el:'barium'} */
4122
- /*particle in ["gamma", "xray", "beta", "alpha", "positron", "electronCapture"]; */
4123
- if ( ( typeof d . e !== "number" ) || ( typeof d . h !== "number" ) || ( typeof d . particle !== "string" ) )
4124
- throw "Reference line is invalid (" + JSON . stringify ( d ) + ")" ;
4125
- } ) ;
4126
- } ) ;
4127
-
4128
- /*this.refLines = JSON.parse(JSON.stringify(data)); /*creates deep copy, but then also have to go through and */
4129
- this . refLines = data ;
4130
- this . refLines . forEach ( function ( a , i ) { a . lines . forEach ( function ( d ) { d . parent = a ; } ) } ) ;
4131
- } catch ( e ) {
4132
- this . refLines = null ;
4133
- console . log ( "invalid input to setReferenceLines" ) ;
4134
- }
4135
- this . refLines = data ;
4136
- }
4116
+ /*this.refLines = JSON.parse(JSON.stringify(data)); //creates deep copy, but then also have to go through and */
4117
+ //
4118
+ this . refLines = data ;
4119
+ let index = 0 ;
4120
+ this . refLines . forEach ( function ( a , i ) {
4121
+ if ( ! a . color )
4122
+ a . color = default_colors [ i % default_colors . length ] ;
4123
+ if ( ! a . lines || ! Array . isArray ( a . lines ) )
4124
+ throw "Reference lines does not contain an array of lines" ;
4125
+
4126
+ a . lines . forEach ( function ( d ) {
4127
+ d . parent = a ;
4128
+ d . id = ++ index ; //We need to assign an ID to use as D3 data, that is unique (energy may not be unique)
4129
+
4130
+ /*{e:30.27,h:6.22e-05,particle:'xray',decay:'xray',el:'barium'} */
4131
+ /*particle in ["gamma", "xray", "beta", "alpha", "positron", "electronCapture"]; */
4132
+ if ( ( typeof d . e !== "number" ) || ( typeof d . h !== "number" ) || ( typeof d . particle !== "string" ) )
4133
+ throw "Reference line is invalid (" + JSON . stringify ( d ) + ")" ;
4134
+ } ) ;
4135
+ } ) ;
4136
+ } catch ( e ) {
4137
+ this . refLines = null ;
4138
+ console . log ( "invalid input to setReferenceLines" ) ;
4139
+ }
4140
+ } //if( !data ) / else
4137
4141
4138
4142
this . redraw ( ) ( ) ;
4139
4143
}
@@ -4145,6 +4149,71 @@ SpectrumChartD3.prototype.setShowRefLineInfoForMouseOver = function( show ) {
4145
4149
self . redraw ( ) ( ) ;
4146
4150
}
4147
4151
4152
+ SpectrumChartD3 . prototype . setKineticReferenceLines = function ( data ) {
4153
+ // data looks like: { fwhm_fcn: function(e){...}, ref_lines: [{weight: 1, src_lines:{color: "red", parent: "Eu152", age: "2.5 HL", lines: [{e: 39.1, h: 0.000135, particle: "xray", desc_ind: 0, parent: Object},....], desc_strs: ["Eu152 to Sm152 via Electron Capture",...]},{...}] }
4154
+ // TODO: Need to validate format of `data`
4155
+
4156
+ if ( data ) {
4157
+ let index = 1000000 ;
4158
+ data . ref_lines . forEach ( function ( a ) {
4159
+ a . src_lines . lines . forEach ( function ( d ) {
4160
+ d . id = ++ index ;
4161
+ d . parent = a . src_lines ;
4162
+ } ) ;
4163
+ } ) ;
4164
+ } //if( data )
4165
+ //console.log( "setKineticReferenceLines:", data );
4166
+
4167
+ this . kineticRefLines = data ;
4168
+
4169
+ this . handleUpdateKineticRefLineUpdate ( ) ;
4170
+ } //SpectrumChartD3.prototype.setKineticReferenceLines
4171
+
4172
+
4173
+ SpectrumChartD3 . prototype . handleUpdateKineticRefLineUpdate = function ( ) {
4174
+ const m = this . getMousePos ( ) ; // Get current mouse position for energy calculation
4175
+ if ( ! this . kineticRefLines || ! this . kineticRefLines . ref_lines || ! this . kineticRefLines . ref_lines . length || ( ( m [ 0 ] == 0 ) && ( m [ 1 ] == 0 ) ) ) {
4176
+ if ( this . currentKineticRefLine ) {
4177
+ this . currentKineticRefLine = null ;
4178
+ this . drawRefGammaLines ( ) ;
4179
+ }
4180
+ return ;
4181
+ } //if( we dont need to draw the lines )
4182
+
4183
+ const energy = this . xScale . invert ( m [ 0 ] ) ;
4184
+ const peak_sigma = ( this . kineticRefLines . fwhm_fcn ? this . kineticRefLines . fwhm_fcn ( energy ) : 2.35482 ) / 2.35482 ;
4185
+
4186
+ // Find the line with the lowest weight across all reference line groups
4187
+ let minWeight = Number . MAX_VALUE ;
4188
+ let bestRefLine = null ;
4189
+
4190
+ for ( const refLineGroup of this . kineticRefLines . ref_lines ) {
4191
+ if ( ! refLineGroup . src_lines || ! refLineGroup . src_lines . lines || ! refLineGroup . src_lines . lines . length ) continue ;
4192
+
4193
+ const src_weight = refLineGroup . weight || 1.0 ;
4194
+ for ( const line of refLineGroup . src_lines . lines ) {
4195
+ if ( line . h <= 0.0 ) continue ;
4196
+ const delta_energy = Math . abs ( energy - line . e ) ;
4197
+ const weight = ( ( 0.25 * peak_sigma + delta_energy ) / line . h ) / src_weight ;
4198
+ if ( ( weight < minWeight ) && ( delta_energy < 5 * peak_sigma ) ) {
4199
+ minWeight = weight ;
4200
+ bestRefLine = refLineGroup . src_lines ;
4201
+ }
4202
+ }
4203
+ }
4204
+
4205
+ if ( bestRefLine && this . refLines && this . refLines . some ( input => bestRefLine . parent == input . parent ) ) {
4206
+ bestRefLine = null ;
4207
+ }
4208
+
4209
+ // If the this.kineticRefLines.ref_lines[i].src_lines that contains the lowest weight is
4210
+ // not equal to this.currentKineticRefLine, then set this.currentKineticRefLine, and call this.drawRefGammaLines()
4211
+ if ( bestRefLine !== this . currentKineticRefLine ) {
4212
+ this . currentKineticRefLine = bestRefLine ;
4213
+ this . drawRefGammaLines ( ) ;
4214
+ }
4215
+
4216
+ } //SpectrumChartD3.prototype.handleUpdateKineticRefLineUpdate
4148
4217
4149
4218
/**
4150
4219
* -------------- Grid Lines Functions --------------
0 commit comments