Skip to content

Commit

Permalink
get not-yet-tested schema working!
Browse files Browse the repository at this point in the history
ref #10-splitter-adapter
  • Loading branch information
maxgrossman committed May 13, 2018
1 parent 43dac25 commit 04b4840
Show file tree
Hide file tree
Showing 10 changed files with 72 additions and 66 deletions.
3 changes: 3 additions & 0 deletions adapters/sequence/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- make a new guy if the # is too large for a sequence
- if the distnace is too close, skip adding that image.
- or if when checking distance and time, one of them is greater than the max
5 changes: 1 addition & 4 deletions adapters/sequence/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ Promise = require('bluebird');

module.exports = (images, params) => {
return Promise.map(images, async (image) => await meta(image))
.then(metas => {
const sortedMetas = metas.sort((a, b) => a.date - b.date);
return split(sortedMetas)
})
.then(async metas => await split(metas, params))
.catch(e => { throw e; })

}
27 changes: 5 additions & 22 deletions adapters/sequence/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,10 @@ const uuidv4 = require('uuid/v4');
* @return {number} euclidean distance between two points
*/
exports.calcDistance = (metaLoc, nextMetaLoc) => {
return distance(
point([metaLoc.lon, metaLoc.lat]),
point([metaLoc.lon, metaLoc.lat])
// { units: 'miles'}
return Math.sqrt(
Math.pow(nextMetaLoc.lon - metaLoc.lon, 2) +
Math.pow(nextMetaLoc.lat - metaLoc.lat, 2)
)

}

/**
Expand All @@ -29,7 +27,7 @@ exports.calcDistance = (metaLoc, nextMetaLoc) => {
* @return {number} milisecond diff between two dates.ee
*
*/
exports.calcDelta = (metaDate, nextMetaDate) => metaDate.diff(nextMetaDate);
exports.calcDelta = (metaDate, nextMetaDate) => nextMetaDate.diff(metaDate) / 1000;

/**
* given a sequence map, adds a new sequence array and returns the map.
Expand All @@ -38,19 +36,4 @@ exports.calcDelta = (metaDate, nextMetaDate) => metaDate.diff(nextMetaDate);
* @param {array} sequence sequence to be added to sequenceMap
* @return {object} updated sequenceMap
*/
exports.addSequence = (sequenceMap, sequence) => { sequenceMap[uuidv4()] = sequence; return sequenceMap };

/**
* given thwo partner meta objects, determines if the two are within user defined time/distnace thresholds
*
* @param {object} meta metadata object at current index of images
* @param {object} partnerMeta metadata object for (either next or previous) partner meta object
*/
exports.withinThresholds = (meta, partnerMeta) => {
const distance = calcDistance(meta.loc, nextMeta.loc);
delta = calcDelta(meta.timestamp, nextMeta.timestamp),
toMuchTime = delta > maxDelta
toFar = distance > maxDistance;

return !toFar && !toMuchTime;
}
exports.addSequence = (sequenceMap, sequence) => { sequenceMap[uuidv4()] = sequence; return sequenceMap };
7 changes: 4 additions & 3 deletions adapters/sequence/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@ module.exports = (paths, cutDist, cutTime, cutSize) => {
.then(async (images) => {
try {
const params = {
dist: cutDist || 0,
detla: cutTime || 0,
maxDist: cutDist || 0.2,
minDist: 0.1,
maxDetla: cutTime || 120,
size: cutSize || 0
},
sequences = await buildSequences(flatten(images), params);

resolve(sequences);
} catch (e) {
reject(e);
Expand Down
3 changes: 1 addition & 2 deletions adapters/sequence/meta.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ Promise = require('bluebird');
*/
module.exports = (image) => {
return new Promise((resolve, reject) =>
exif
.read(image)
exif.read(image)
.then(tags => {
resolve({
image: image,
Expand Down
64 changes: 37 additions & 27 deletions adapters/sequence/split.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,57 @@

const calcDistance = require('./helpers').calcDistance;
const calcDelta = require('./helpers').calcDelta;
const addSequence = require('helpers').addSequence
const withinThresholds = require('helpers').withinThresholds;
const addSequence = require('./helpers').addSequence

Promise = require('bluebird');

/**
* provided list of image metadata objects and thresholds for
* provided list of image metadata objects and thresholds used to define sequences,
* build and reply an object of image sequences
*
* @param metas {list} list of image metadata objects
* @param params {object} map of user (or default) tresholds used to build sequences
* @return {object} map of generated image sequences
*
*/
module.exports = (metas, params) => {
const sortedMetas = metas.sort((a, b) => a.timestamp - b.timestamp),
pelIndex = sortedMetas.length - 2,
lastIdx = sortedMetas.length - 1,
sequences = {},
sequenceless = [];
maxDist = params.dist,
maxDelta = params.delta,
maxSize = params.maxSize;
sequenceless = [],
maxDist = params.maxDist,
maxDelta = params.maxDelta,
maxSize = params.maxSize,
minDist = params.minDist;

let currentSequence = [];

Promise.all(sortedMetas, (meta, i) => {
if (currentSequence.length === maxSize) {
sequences = addSequence({}, currentSequence);
currentSequence = [];

}

const partnerMeta = sortedMetas[i + (i <= pelIndex ? 1 : -1)],
meetsThreshold = withinThresholds(meta, partnerMeta);

if (meetsThreshold) {
// for the 1st to 2nd to last meta...
sortedMetas.slice(0, pelIndex).forEach((meta, i) => {
const partnerMeta = sortedMetas[i + 1],
distance = calcDistance(meta.loc, partnerMeta.loc),
tooClose = false;
// tooClose = distance < minDist;

// ... if image is not too close to its partner, add it to a sequence.
if (!tooClose) {
// ... if the current sequence length matches the maximum size,
// or images are too far apart (in space or time),
// add the current sequence to the sequence map, then make a new sequence.
const delta = calcDelta(meta.timestamp, partnerMeta.timestamp),
needNewSequence = currentSequence.length === maxSize || distance > maxDist || delta > maxDelta;

if (needNewSequence) {
addSequence(sequences, currentSequence);
currentSequence = [];

}

currentSequence.push(meta);

} else {
sequenceless.push(meta);
}

})
.then(() => {
return { sequences: sequences, sequenceless: sequenceless}
}
})


if (currentSequence.length > 0) addSequence(sequences, currentSequence);
return sequences;
};
3 changes: 2 additions & 1 deletion schema/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use strict';

module.exports = {
metadata: require('./metadata')
metadata: require('./metadata'),
sequences: require('./sequences')
}
7 changes: 2 additions & 5 deletions schema/metadata.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ const locSchema = Joi
* invalid: '2008-9-23T14:27:07.240Z'
*/
const timeStampSchema = Joi.object();
// Joi
// .string()
// .regex(/([1-2]{1}[0-9]{3})-([0-1]{1}[0-9]{1})-([0-3]{1}[0-9]{1})T([0-2]{1}[0-9]{1}):([0-6]{1}[0-9]{1}):([0-6]{1}[0-9]{1}).[0-9]{3}Z/)

module.exports = Joi
.object()
Expand All @@ -46,6 +43,6 @@ module.exports = Joi
})
.requiredKeys(
'image',
'loc'
// 'timestamp'
'loc',
'timestamp'
)
12 changes: 12 additions & 0 deletions schema/sequences.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use strict';

const Joi = require('joi');
const metadata = require('./metadata');

module.exports = Joi
.object()
.pattern(
// uuid regex;
/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,
Joi.array().items(metadata)
);
7 changes: 5 additions & 2 deletions test/adapters/sequencerSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const Joi = require('joi');

/* schemas that define valid/expected function outputs */
const metadataSchema = require('../../schema').metadata;
const sequencesSchema = require('../../schema').sequences;

/* seqeunce adapter components */
const meta = require('../../adapters/sequence/meta');
Expand All @@ -33,9 +34,11 @@ describe('sequence', () => {
it ('given a path of images, generates a list of sequence objects', async () => {
try {
const paths = ['/testData/exif-gps-samples'].map(p => process.cwd() + p),
sequences = await sequenceAdapter(paths);
sequences = await sequenceAdapter(paths),
validation = Joi.validate(sequences, sequencesSchema);

console.log(sequences)
expect(validation.value).to.be.eql(sequences)
expect(validation.error).to.be.null;

} catch (e) {
console.error(e);
Expand Down

0 comments on commit 04b4840

Please sign in to comment.