Skip to content

Commit dc6fe24

Browse files
authored
Merge pull request #35 from jywarren/spectrum-images
images now belong to spectra, spectra can be created from images
2 parents 5084187 + cb81d91 commit dc6fe24

11 files changed

+284
-175
lines changed

dist/spectral-workbench.js

Lines changed: 115 additions & 77 deletions
Large diffs are not rendered by default.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "spectral-workbench",
3-
"version": "0.0.15",
3+
"version": "0.1.0",
44
"description": "Framework for spectrometric data management & analysis by Public Lab",
55
"main": "dist/spectral-workbench.js",
66
"scripts": {

spec/javascripts/graph_spec.js

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ describe("Graph", function() {
7575
calibrated: true, // 269.089 to 958.521
7676
range: [400, 800],
7777
onComplete: callback,
78-
onImageComplete: function() { done(); } // fires when graph.image is loaded, so that later tests can run
78+
onImageComplete: function() { done(); } // fires when graph.datum.image is loaded, so that later tests can run
7979

8080
});
8181

@@ -107,7 +107,7 @@ describe("Graph", function() {
107107
// expect(graph.width).toBe(600); // this prob depends on the container
108108
expect(graph.zooming).toBe(false);
109109
expect(graph.el.html()).toBeDefined();
110-
expect(graph.image.el.html()).toBeDefined();
110+
expect(graph.datum.image.el.html()).toBeDefined();
111111
expect(graph.svg).toBeDefined();
112112

113113
expect(graph.svg).toBeDefined();
@@ -122,19 +122,19 @@ describe("Graph", function() {
122122
expect(graph.extent).toBeDefined();
123123
expect(graph.fullExtent).toBeDefined();
124124
expect(graph.fullExtent[1] - graph.fullExtent[0]).toBeGreaterThan(graph.extent[1] - graph.extent[0]);
125-
expect(graph.image).toBeDefined();
126-
expect(graph.image.el).toBeDefined();
127-
expect(graph.image.width).toBeDefined();
125+
expect(graph.datum.image).toBeDefined();
126+
expect(graph.datum.image.el).toBeDefined();
127+
expect(graph.datum.image.width).toBeDefined();
128128

129129
});
130130

131131

132132
var originalPxPerNm;
133133

134134
it("imagePxToDisplayPx() converts an x-coordinate pixel value from image space to a display space pixel value", function() {
135-
originalPxPerNm = originalPxPerNm = graph.image.width / (graph.fullExtent[1] - graph.fullExtent[0]);
135+
originalPxPerNm = originalPxPerNm = graph.datum.image.width / (graph.fullExtent[1] - graph.fullExtent[0]);
136136

137-
// image 800px wide (graph.image.width), normally displayed at 800px,
137+
// image 800px wide (graph.datum.image.width), normally displayed at 800px,
138138
// but with 400-800 range limiting pushing it wider; 1189.27px
139139
// source spectrum goes from 269.089nm to 958.521nm, or a range of 689.432nm
140140
// so, 130.911nm between start and range start (400)
@@ -143,14 +143,14 @@ describe("Graph", function() {
143143
// and pxPerNm should be 1.1603754975109946
144144
// margins make displayed image width more difficult to calculate:
145145
// default margin = { top: 10, right: 30, bottom: 20, left: 70 }; but right margin is not used in image display
146-
// but we can use graph.image.el.width() for the final displayed width:
146+
// but we can use graph.datum.image.el.width() for the final displayed width:
147147

148148
// 130 nm in original image pixels;
149149
expect(Math.round(graph.imagePxToDisplayPx(originalPxPerNm * 130.911))).toBeCloseTo(0);
150150
// graph.width is 690px, displayed image, cropped
151151

152152
var rightEdgeNm = 689.432 - 158.521; // full range in nm minus hidden right side should be right edge in nm
153-
expect(Math.round(graph.imagePxToDisplayPx(originalPxPerNm * rightEdgeNm))).toBeCloseTo(Math.round(graph.image.container.width()));
153+
expect(Math.round(graph.imagePxToDisplayPx(originalPxPerNm * rightEdgeNm))).toBeCloseTo(Math.round(graph.datum.image.container.width()));
154154

155155
});
156156

@@ -166,7 +166,7 @@ describe("Graph", function() {
166166
so 500/800 = 0.625, times 680 = 425
167167
*/
168168

169-
expect(graph.image.container.width()).toBe(680);
169+
expect(graph.datum.image.container.width()).toBe(680);
170170
expect(graph.imagePxToDisplayPx(500)).toBeCloseTo(425);
171171

172172
graph.range = range;
@@ -225,7 +225,7 @@ describe("Graph", function() {
225225

226226
expect(Math.round(graph.imagePxToDisplayPx(originalPxPerNm * 130.911))).toBeCloseTo(-1); // rounding error; toBeCloseTo(0, 1) syntax doesn't seem to work for precision?
227227
var rightEdgeNm = 689.432 - 158.521; // displayed range in nm (~400) minus hidden right side should be right edge in nm
228-
expect(Math.round(graph.imagePxToDisplayPx(originalPxPerNm * rightEdgeNm))).toBeCloseTo(graph.image.container.width() + 1); // rounding error
228+
expect(Math.round(graph.imagePxToDisplayPx(originalPxPerNm * rightEdgeNm))).toBeCloseTo(graph.datum.image.container.width() + 1); // rounding error
229229
expect(Math.round(graph.imagePxToDisplayPx(500))).toBeCloseTo(675);
230230

231231
expect(graph.displayPxToNm(0)).toBeCloseTo(graph.extent[0]);

spec/javascripts/image_spec.js

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,21 @@ describe("Image", function() {
88

99
});
1010

11+
1112
it("should not be undefined even if it has no graph or DOM element", function(done) {
1213

1314
image = new SpectralWorkbench.Image(
1415
false,
1516
{
16-
callback: done // options
17+
onLoad: done // options
1718
}
1819
);
1920

2021
expect(image).toBeDefined();
2122

2223
});
2324

25+
2426
it("has defined width and height", function() {
2527

2628
expect(image.width).toBeDefined();
@@ -30,15 +32,34 @@ describe("Image", function() {
3032

3133
});
3234

35+
3336
it("has a canvas element and context", function() {
3437

3538
expect(image.canvasEl).toBeDefined();
36-
expect(image.canvasEl.length).toBeGreaterThan(1);
39+
expect(image.canvasEl.length).toEqual(1);
3740
expect(image.canvasEl.width()).toEqual(image.width);
3841
expect(image.canvasEl.height()).toEqual(image.height);
3942
expect(image.ctx.canvas.width).toEqual(image.width);
4043
expect(image.ctx.canvas.height).toEqual(image.height);
4144

4245
});
4346

47+
48+
it("can be constructed from an image url", function(done) {
49+
50+
var imageFromUrl = new SpectralWorkbench.Image(false, {
51+
url: 'spec/javascripts/fixtures/test-spectrum-9.png',
52+
onLoad: function onLoad() {
53+
54+
expect(imageFromUrl.obj).not.toBeUndefined();
55+
expect(imageFromUrl.width).not.toBeUndefined();
56+
57+
done();
58+
59+
}
60+
});
61+
62+
});
63+
64+
4465
});

spec/javascripts/spectrum_spec.js

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ describe("Spectrum", function() {
88
// {"average":64.3333,"r":69,"g":46,"b":78,"wavelength":269.089},
99
// {"average":31,"r":33,"g":19,"b":41,"wavelength":958.521}
1010

11-
var spectrum = new SpectralWorkbench.Spectrum(data)
11+
var spectrum = new SpectralWorkbench.Spectrum(data);
1212

1313
it("is not undefined when initialized with spectrum json", function() {
1414

@@ -283,19 +283,31 @@ describe("Spectrum", function() {
283283

284284
});
285285

286-
// test spectrum.image, which the following method uses; here, we don't have an image.
287-
288-
289286
/* ======================================
290287
* Overwrite spectrum.json.data.lines, the raw JSON of the spectrum
291288
* <y> is the y-position of the cross section of pixels, where 0 is the top row
292289
* <keepCalibrated> is a boolean which indicates whether to keep or flush the calibration
293290
* spectrum.imgToJSON = function(y, keepCalibrated) {
294291
*/
295-
xit("imgToJSON() extracts JSON data from an image", function() {
292+
it("imgToJSON() extracts JSON data from an image", function(done) {
293+
294+
var image = new SpectralWorkbench.Image(false, {
295+
url: 'spec/javascripts/fixtures/test-spectrum-9.png',
296+
onLoad: function onLoad() {
297+
298+
var spectrumFromImage = new SpectralWorkbench.Spectrum(image, false, { y: 10 });
299+
300+
expect(spectrumFromImage.image).toBeDefined();
301+
302+
// check that we can extract image data
303+
expect(spectrumFromImage.imgToJSON(1)[0].average).toBe(64.33);
304+
expect(spectrumFromImage.imgToJSON(1)[0].pixel).toBe(0);
305+
expect(spectrumFromImage.imgToJSON(1)[0].wavelength).toBeUndefined();
306+
307+
done();
296308

297-
// check that we can extract image data
298-
expect(graph.datum.imgToJSON(1)).toBe(64.3333);
309+
}
310+
});
299311

300312
});
301313

src/SpectralWorkbench.Datum.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@ SpectralWorkbench.Datum = Class.extend({
22

33
init: function(args, _graph) {
44

5-
this.args = args;
6-
7-
this.json = args;
8-
this.title = args.title;
9-
this.id = args.id;
10-
this.graph = _graph;
11-
this.tags = [];
12-
this.powertags = [];
13-
145
var _datum = this;
156

7+
_datum.args = args;
8+
9+
if (_datum.args.data || _datum.args.spectra) _datum.json = args;
10+
_datum.title = args.title;
11+
_datum.id = args.id;
12+
_datum.graph = _graph;
13+
_datum.tags = [];
14+
_datum.powertags = [];
15+
1616

1717
/* ======================================
1818
* Turns <a> link with specified selector into a download

src/SpectralWorkbench.Graph.js

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,6 @@ SpectralWorkbench.Graph = Class.extend({
2727

2828
_graph.dataType = "spectrum";
2929

30-
// Create an image and canvas element to display and manipulate image data.
31-
// We could have this non-initialized at boot, and only create it if asked to.
32-
_graph.image = new SpectralWorkbench.Image(_graph, {
33-
callback: _graph.onImageComplete,
34-
selector: _graph.args.imageSelector,
35-
url: _graph.args.imgSrc,
36-
sample_row: _graph.args.sample_row
37-
});
38-
3930
} else if (_graph.args.hasOwnProperty('set_id')) {
4031

4132
_graph.dataType = "set";
@@ -121,9 +112,9 @@ SpectralWorkbench.Graph = Class.extend({
121112
_graph.imagePxToDisplayPx = function(x) {
122113

123114
// what proportion of the full image is being displayed?
124-
var proportion = x / _graph.image.width, // x position as a percent of original image
125-
scaledX = proportion * _graph.image.el.width(), // that proportion of the displayed DOM image element;
126-
displayPxPerNm = _graph.image.el.width() / (_graph.fullExtent[1] - _graph.fullExtent[0]),
115+
var proportion = x / _graph.datum.image.width, // x position as a percent of original image
116+
scaledX = proportion * _graph.datum.image.el.width(), // that proportion of the displayed DOM image element;
117+
displayPxPerNm = _graph.datum.image.el.width() / (_graph.fullExtent[1] - _graph.fullExtent[0]),
127118
leftXOffsetInDisplayPx = (_graph.extent[0] - _graph.fullExtent[0]) * displayPxPerNm;
128119

129120
return scaledX - leftXOffsetInDisplayPx;
@@ -138,11 +129,11 @@ SpectralWorkbench.Graph = Class.extend({
138129
_graph.displayPxToImagePx = function(x) {
139130

140131
// what proportion of the full image is being displayed?
141-
var displayPxPerNm = _graph.image.el.width() / (_graph.fullExtent[1] - _graph.fullExtent[0]),
132+
var displayPxPerNm = _graph.datum.image.el.width() / (_graph.fullExtent[1] - _graph.fullExtent[0]),
142133
leftXOffsetInDisplayPx = (_graph.extent[0] - _graph.fullExtent[0]) * displayPxPerNm,
143134
fullX = x + leftXOffsetInDisplayPx, // starting from true image DOM element zero
144-
proportion = fullX / _graph.image.el.width(), // x position as a percent of DOM image
145-
scaledX = proportion * _graph.image.width; // that proportion of the original image
135+
proportion = fullX / _graph.datum.image.el.width(), // x position as a percent of DOM image
136+
scaledX = proportion * _graph.datum.image.width; // that proportion of the original image
146137

147138
return scaledX;
148139

@@ -267,6 +258,15 @@ SpectralWorkbench.Graph = Class.extend({
267258

268259
if (_graph.dataType == "spectrum") {
269260

261+
// Create an image and canvas element to display and manipulate image data.
262+
_graph.datum.image = new SpectralWorkbench.Image(_graph, {
263+
onLoad: _graph.onImageComplete,
264+
selector: _graph.args.imageSelector,
265+
// plus optionals:
266+
url: _graph.args.imgSrc,
267+
sample_row: _graph.args.sample_row
268+
});
269+
270270
_graph.UI = new SpectralWorkbench.UI.Spectrum(_graph);
271271

272272
// scan for helper tips
@@ -553,7 +553,7 @@ SpectralWorkbench.Graph = Class.extend({
553553

554554
_graph.el.height(100); // this isn't done later because we mess w/ height, in, for example, calibration
555555

556-
if (_graph.image) _graph.image.updateSize(); // adjust image element and image.container element
556+
if (_graph.datum && _graph.datum.image) _graph.datum.image.updateSize(); // adjust image element and image.container element
557557

558558
if (_graph.datum) {
559559

src/SpectralWorkbench.Image.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ SpectralWorkbench.Image = Class.extend({
4646

4747
// We're in a browser; build a canvas element, but hide it.
4848
$('body').append('<canvas id="spectral-workbench-canvas" style="display:none;"></canvas>;');
49-
image.canvasEl = $('canvas#spectral-workbench-canvas');
49+
image.canvasEl = $('canvas#spectral-workbench-canvas:last');
5050
image.canvasEl.width(image.width);
5151
image.canvasEl.height(image.height);
5252
image.ctx = image.canvasEl[0].getContext("2d");
@@ -59,7 +59,7 @@ SpectralWorkbench.Image = Class.extend({
5959

6060
if (image.options.sample_row) image.setLine(image.options.sample_row);
6161

62-
if (image.options.callback) image.options.callback(); // since image loading is asynchronous
62+
if (image.options.onLoad) image.options.onLoad(); // since image loading is asynchronous
6363

6464
}
6565

0 commit comments

Comments
 (0)