Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New @turf-isobands module with MarchingSquares #619

Merged
merged 31 commits into from May 9, 2017

Conversation

stebogit
Copy link
Collaborator

@stebogit stebogit commented Mar 15, 2017

  • Use a meaningful title for the pull request. Include the name of the package modified.
  • Have read How To Contribute.
  • Run npm test at the sub modules where changes have occured.
  • Run npm run lint to ensure code style at the turf module level. --> not sure how/if it works

@stebogit
Copy link
Collaborator Author

@DenisCarriere
I tried to run eslint but I got so many errors (like 18000)... Is it possible that they are not only caused by my code? I noticed that it's asked to use AirBnB style guide, which has recently deprecated ES5, while turf uses ES5 only. Isn't that an issue?

I don't know how travis works, could you please give me some hint on how to set/fix it?

Thanks

@DenisCarriere
Copy link
Member

DenisCarriere commented Mar 15, 2017

@stebogit 👍 Thanks attempting this, the linting is done at the TurfJS root level.

Once you are in the root folder:

$ npm install
$ npm run lint

So far the isobands turf linting related errors are:

You can also see this in the build logs https://travis-ci.org/Turfjs/turf/builds/211360094

/home/travis/build/Turfjs/turf/packages/turf-isobands/index.js
   12:1   error  Expected JSDoc for 'pointGrid' but found 'grid'                                                valid-jsdoc
   38:1   error  Trailing spaces not allowed                                                                    no-trailing-spaces
   40:1   error  Trailing spaces not allowed                                                                    no-trailing-spaces

@stebogit
Copy link
Collaborator Author

stebogit commented Mar 15, 2017

thanks!
I'll fix the issues later this evening.
I see also marchingsquare.js has a bunch of styling issues, is it acceptable being that an external (minified) library?

- "4"
before_install:
- npm install -g npm@~3.8.9

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is not needed since TurfJS has .travis.yml at the root level

@@ -0,0 +1,2 @@
test
coverage
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed since this is covered in the package.json using "files": ["index.js", "index.d.ts"]

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What exactly is not needed? the .npmignore file?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The entire .npmignore file is not required, I've changed every module in Turf so all of them have the same syntax & file structure.

Use any turf module as your starting point to propose a new module (except the index.js).
https://github.com/Turfjs/turf/tree/master/packages/turf-along

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2016 Stefano Borghi
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've been using TurfJS as a generic name for all licenses (also 2017)

.on('complete', function () {

})
.run();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feel free to write in ES6 👍 bench.js & test.js is your only chance to write arrow functions :)

* http://turfjs.org/docs/#isolines
*/
declare function isobands(points: Points, z: string, resolution: number, breaks: Array<number>): LineStrings;
declare namespace isolines { }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

namespace must be the same name as the function name.

This breaks the typescript definition.

* var breaks = [0, 5, 8.5];
* var isobands = turf.isobands(pointGrid, 'z', breaks);
* //=isobands
******************************************************************/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above **/

divide points in pointGrid by latitude, creating a 2-dimensional data grid
####################################*/
var pointsByLatitude = {};
for (var j = 0; j < points.length; j++) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try using one of the @turf/meta functions, coordEach() or featureEach()

"name": "turf-isobands",
"version": "2.0.0",
"description": "turf isobands module",
"main": "index.js",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Include "types":"index.d.ts" (next to main instead of at the bottom) & "files": ["index.js", "index.d.ts"]

"description": "turf isobands module",
"main": "index.js",
"scripts": {
"test": "tape test.js"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add benchmark to scripts

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is "bench": "node bench.js" ok?

var isobands = require('./');

test('isobands', function(t){
var points = JSON.parse(fs.readFileSync(__dirname + '/geojson/Points.geojson'));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to make your tests have dynamic data loading instead of hard coded fixtures in your tests.
That way someone can expand easily the test cases by simply adding a new .geojson to the test/in.

@turf/union has a good example of that:
https://github.com/Turfjs/turf/blob/master/packages/turf-union/test.js

@DenisCarriere
Copy link
Member

@stebogit As for the MarchingSquare.js file, I would not include it as a minified file, does it exists on npm?

@stebogit
Copy link
Collaborator Author

@DenisCarriere
no, MarchingSquare.js does not have an npm module (yet @RaumZeit ?). Is there a way to exclude it when linting?
Also, the name of the MS function Isobands is uppercase, which eslint doesn't like...

@DenisCarriere
Copy link
Member

Quick eslint trick is you can include this around your code to ignore "valid" lines that cause errors.

/*eslint-disable*/
var isobands = MarchingSquaresJS.IsoBands(gridData, lowerBand, upperBand - lowerBand);
/*eslint-enable*/

@DenisCarriere
Copy link
Member

@stebogit Glancing at the repo, I'm thinking we should drop (make optional) the @param {string} z in favor of the geometry.coordinates (x, y, z).

The GeoJSON specs only allows (longitude, latitude, elevation/altitude) to be a valid geometry.
http://geojson.org/geojson-spec.html#positions

Proposed valid input

var points = {
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "Point",
        "coordinates": [
          7,
          42,
          300
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "Point",
        "coordinates": [
          10,
          45,
          230
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "Point",
        "coordinates": [
          5,
          45,
          215
        ]
      }
    }
  ]
}
var results = isobands(points, [200, 250, 300])

t.deepEqual(isobanded, load.sync(directories.out + 'isobands' + idx), input.name);
if (process.env.REGEN) write.sync(directories.out + filename, results);
t.equal(results.features[0].geometry.type, 'MultiPolygon', name + ' geometry=MultiPolygon');
t.deepEqual(results, load.sync(directories.out + filename), name);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this way the code looks definitely nicer, but the content of the output file, points1.geojson, is not a collection of points, but actually of multipolygons or isobands.
don't you think it might be a little confusing?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test/in & test/out should be the same filename. That way it's clear what goes in and what goes out.

You can even call points.geojson italy.geojson and then the output would be test/out/italy.geojson

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This becomes more evident when you start adding more and more files in the test/in, for example @turf/union has many files.

https://github.com/Turfjs/turf/tree/master/packages/turf-union/test/in

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then I'd call them input1.geojson, input2.geojson and so on 😄
not a biggie though

@stebogit
Copy link
Collaborator Author

I get your point.
However the input are points, which might have multiple properties you want to chart (I'm not charting elevation for example, but estimated count of bugs 😄), so specifying the name might be useful.
If made optional the default might certainly be elevation or altitude

@DenisCarriere
Copy link
Member

@stebogit 👍 Valid point, I think having it optional would be a good idea, or at least have that param at the end of the function.

function (pointGrid, breaks, z)

We could have z as default z="elevation" or even better read the z coordinate from [x,y,z].

We can add that logic at the beginning as part of the user input validation by reading the first point entry and figuring out if his FeatureCollection<Point> is valid or not (if he is using properties or z coordinates).

@stebogit
Copy link
Collaborator Author

@DenisCarriere great! 🎉
z at the end of the function makes it easy and effective.
Never thought about having an input validation, good point! 👍

@DenisCarriere
Copy link
Member

@stebogit I will have a stab at it over the weekend, also there's a lot of "complicated" logic inside the index.js that can be replaced by @turf/meta methods (coordEach(), featureEach(), etc..).

@stebogit
Copy link
Collaborator Author

@DenisCarriere Thanks, I'm not familiar with the meta functions and I haven't worked on my contour project so it might take a while for me to correctly make the changes.
I believe you are more into turf/GeoJSON standards and details for input validation.
Let me know if/how I can help though

@DenisCarriere
Copy link
Member

No worries, I have this habit of refactoring code until the most minimal amounts of lines are needed.

At least we have a "functional" prototype of isobands, the next steps would simply be making sure the code is running as fast as it possibly can and without any memory leaks.

@DenisCarriere
Copy link
Member

DenisCarriere commented Mar 16, 2017

@stebogit another idea for the breaks param. We could have both of the following as valid inputs:

  • Array<number> (explicitly define each break)
  • number (define each break by a fix interval)

Scenario: User wants to create contour lines based on 25 meter intervals (elevation units must also be in meters or the desired unit which is the same as the breaks).

@stebogit
Copy link
Collaborator Author

@DenisCarriere splendid idea!

@RaumZeit
Copy link

MarchingSquaresJS is now available through npm as marchingsquares module. Note, however, that due to npm naming conventions I've reverted the public API function names to lower camel case since version 1.2.0 of MarchingSquaresJS, i.e. the IsoBands function is now named isoBands.

@DenisCarriere
Copy link
Member

@stebogit Let me know if you are happy to merge this module, looks good to me 👍 .

Always room for improvements/fixes in future releases.

Also, feel free to add your matrix-to-grid & grid-to-matrix module once it's stable.

@DenisCarriere DenisCarriere added this to the 4.2.0 milestone Apr 17, 2017
@stebogit
Copy link
Collaborator Author

stebogit commented Apr 17, 2017

@DenisCarriere personally I would remove the random input interpolation (the createPointGrid function is not actually working correctly), just requiring the input to be a pointGrid. I'll work on fixing the output offset and I want to create few more tests to make sure the output is actually right (here matrix-to-grid will be useful).

Also, feel free to add your matrix-to-grid & grid-to-matrix module once it's stable.

Do you mean in this module? My idea was to use them in @turf/interpolate (#24, still under construction...), which I thought would allow users to create/clean the input for isobands and isolines, leaving the input handling outside them. Or, we might include the validation with@turf/interpolate once completed.

@DenisCarriere
Copy link
Member

DenisCarriere commented Apr 17, 2017

Oh I thought that createGridData was grid-to-matrix, however it doesn't look like it's exactly the same thing.

👍 Yep, you can remove the random fixture, we can always add it later in a future minor release.

Looking forward to publishing this module! 🚀

@stebogit Have a last glance at this module and merge this PR whenever you feel comfortable with it.

@stebogit
Copy link
Collaborator Author

@DenisCarriere I created a few more tests for isobands and I can tell there are few things that are not quite right, the output is not reliable. MarchingSquare even seems to return some unexpected outputs sometimes, but I'm not sure yet.
I'll keep working on this, but unfortunately I believe it's not gonna be quick... sorry 😞

@DenisCarriere
Copy link
Member

@stebogit No rush... (take all the time in the world 👍 ).

even seems to return some unexpected outputs sometimes

I agree, MarchingSquare is a bit foreign to me, you're the one with the most experience using this library.

Keep it up!

- set aside z-coordinate test;
- fixed output dimensions issue;
- added grid-to-matrix dependancy;
@stebogit
Copy link
Collaborator Author

Fixed output bug, next will add more tests with graphically easy-to-read grid/matrix input values, then will evaluate performances.

@DenisCarriere DenisCarriere modified the milestones: 4.3.0, 4.2.0 Apr 30, 2017
added tests;
updated benchmark;
updated readme;
introduced common and per isoband options;
@stebogit
Copy link
Collaborator Author

stebogit commented May 8, 2017

@DenisCarriere please take a look at the module, and feel free to add more tests.
I added a common and an individual properties object as options, useful to style the isobands.
Now that I think about it, for some reason I removed the use of z-coordinate 😅 , we probably want to restore it.
I think we could consider this done as a first working version.
Lots of room for improvements though, in particular in performance and output validation for more strict maps like Google.

@DenisCarriere DenisCarriere modified the milestones: 4.3.0, 4.4.0 May 8, 2017
@DenisCarriere
Copy link
Member

DenisCarriere commented May 9, 2017

Works for me! 👍 This will be released in the next minor release v4.3 (aiming to get that done tonight Soon 🤓 )

@DenisCarriere DenisCarriere merged commit 910d5f5 into Turfjs:master May 9, 2017
@DenisCarriere DenisCarriere modified the milestones: 4.3.0, 4.4.0 May 9, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants