UNPKG

@modelx/modelx

Version:

Construct AI & ML models with JSON using Typescript & Tensorflow

349 lines (316 loc) 12.3 kB
import * as ModelXDataTypes from '@modelx/data/src/DataSet'; import { DateTime, DateTimeJSOptions, DateObject, } from 'luxon'; import Outlier from 'outlier'; export enum Dimensions { YEARLY='yearly', WEEKLY='weekly', MONTHLY='monthly', HOURLY='hourly', DAILY='daily', MINUTELY='minutely', SECONDLY='secondly', } export enum BooleanAnswer { UNKNOWN = -1, FALSE = 0, TRUE = 1, } export interface ParsedDate extends DateObject{ hour?: number; minute?: number; week?: number; //weekNumber ordinal_day?: number; //ordinal days_in_month?: number; //daysInMonth weekend?: boolean; quarter_hour?: number; } export type Entity = { [index: string]: any; } export type LuxonDateTimeAndFormat = { date: DateTime; format: string; } export function getLuxonDateTime(options: { time_zone?: string; dateObject: Date|string; dateFormat?: string; }):LuxonDateTimeAndFormat { const { dateObject, dateFormat, } = options; if (dateFormat === 'js' && typeof dateObject === 'object' || (typeof dateObject === 'object' && dateObject instanceof Date)) { return { date: DateTime.fromJSDate(dateObject as Date, { zone: options.time_zone, }), format: 'js', }; } else if (typeof dateFormat === 'string' && dateFormat !== 'iso' && dateFormat !== 'js') { return { date: DateTime.fromFormat(dateObject as string, dateFormat, { zone: options.time_zone, }), format: dateFormat, }; } else { return { date: DateTime.fromISO(dateObject as string, { zone: options.time_zone, }), format: 'iso', }; } } // const yearNumbers = []; const generatedMonthNumbers = []; const generatedWeekNumbers = []; const generatedDayNumbers = []; const generatedQuarterhourNumbers = []; const generatedOrdinalDayNumbers = []; const generatedHourNumbers = []; const generatedMinuteNumbers = []; const generatedSecondNumbers = []; const generatedMockDateObject = { year: new Date().getFullYear(), month: 1, day: 1, hour: 0, minute: 0, second: 0, week: 1, weekday: 1, quarter_hour: 1, oridinalday:1, }; const generatedMockDates = [generatedMockDateObject, ]; for (let i = 0; i <= 366; i++){ const newMockDate = Object.assign({}, generatedMockDateObject); if (i >= 1 && i <= 12) { newMockDate.month = i; generatedMonthNumbers.push(i); } if (i >= 1 && i <= 52) { newMockDate.week = i; generatedWeekNumbers.push(i); } if (i >= 1 && i <= 7) { newMockDate.weekday = i; generatedDayNumbers.push(i); } if (i >= 1 && i <= 366) { newMockDate.oridinalday = i; generatedOrdinalDayNumbers.push(i); } if (i >= 1 && i <= 31) { newMockDate.day = i; generatedDayNumbers.push(i); } if (i >= 1 && i <= 96) { newMockDate.quarter_hour = i; generatedQuarterhourNumbers.push(i); } if (i <= 23) { newMockDate.hour = i; generatedHourNumbers.push(i); } if (i <= 59) { newMockDate.minute = i; generatedMinuteNumbers.push(i); } if (i <= 59) { newMockDate.second = i; generatedSecondNumbers.push(i); } generatedMockDates.push(newMockDate); } export type TrainingProgressUpdate = { completion_percentage: number; loss: number; epoch: number; logs: { loss: number }; status: string; defaultLog?: boolean; } export function training_on_progress({ completion_percentage, loss, epoch, status, logs, defaultLog=true }:TrainingProgressUpdate):void { if(defaultLog) console.log({ completion_percentage, loss, epoch, status, logs }); } export type TrainingProgressCallback =({ completion_percentage, loss, epoch, status, logs }:TrainingProgressUpdate)=> void; export const mockDates = generatedMockDates; export function getPartialHour(minute:number):number { const partialHour = minute / 15; if (partialHour < 1) { return 1; } else if (partialHour < 2) { return 2; } else if (partialHour < 3) { return 3; } else { return 4; } } export function getQuarterHour(parsedDate: ParsedDate):number { if(typeof parsedDate.hour ==='undefined' || typeof parsedDate.minute ==='undefined') throw new ReferenceError('both hour and minute are required') return parsedDate.hour * 4 + getPartialHour(parsedDate.minute); } export function getParsedDate(date:Date, options?:DateTimeJSOptions): ParsedDate { const luxonDate = DateTime.fromJSDate(date, options); const parsedDate:ParsedDate = Object.assign({}, luxonDate.toObject()); parsedDate.week = luxonDate.weekNumber; parsedDate.ordinal_day = luxonDate.ordinal; parsedDate.weekday = luxonDate.weekday; parsedDate.days_in_month = luxonDate.daysInMonth; parsedDate.weekend = (luxonDate.weekday === 6 || luxonDate.weekday === 7) ? true : false; parsedDate.quarter_hour = getQuarterHour(parsedDate); return parsedDate; } export function getLocalParsedDate({ date, time_zone, dimension, }: { date: Date; time_zone: string; dimension: Dimensions; }) { //modelDoc.dimension const end_date = DateTime.fromJSDate(date).plus({ //@ts-ignore [ timeProperty[ dimension ] ]: 1, }).toJSDate(); const startOriginDate = DateTime.fromJSDate(date, { zone:time_zone, }); const endOriginDate = DateTime.fromJSDate(end_date, { zone:time_zone, }); const startDate = DateTime.fromJSDate(date); const endDate = DateTime.fromJSDate(end_date); const { year, month, day, ordinal, weekday, hour, minute, second, } = startOriginDate; return { year, month, day, hour, minute, second, days_in_month: startOriginDate.daysInMonth, ordinal_day: ordinal, week: startOriginDate.weekNumber, weekday: weekday, weekend: (startOriginDate.weekday >= 6), origin_time_zone: time_zone, start_origin_date_string: startOriginDate.toFormat(prettyTimeStringOutputFormat), // start_local_date_string, start_gmt_date_string: startDate.toJSDate().toUTCString(), end_origin_date_string: endOriginDate.toFormat(prettyTimeStringOutputFormat), // end_local_date_string, end_gmt_date_string: endDate.toJSDate().toUTCString(), }; } export const prettyTimeStringOutputFormat = 'ccc, dd LLL yyyy TTT'; export const timeProperty = { [Dimensions.MONTHLY]:'months', [Dimensions.WEEKLY]:'weeks', [Dimensions.DAILY]:'days', [Dimensions.HOURLY]:'hours', }; export const durationToDimensionProperty = { 'years':Dimensions.YEARLY, 'weeks':Dimensions.WEEKLY, 'months':Dimensions.MONTHLY, 'days':Dimensions.DAILY, 'hours': Dimensions.HOURLY, }; export const featureTimeProperty = { weekly:'week', monthly:'month', hourly:'hour', daily:'day', }; export const dateTimeProperty = { weekly:'weekNumber', monthly:'month', hourly:'hour', daily:'day', }; export const performanceValues = { monthly: 6, weekly: 26, daily: 30, hourly: 48, }; export const ISOOptions = { includeOffset: false, // suppressSeconds:true, suppressMilliseconds: true, }; export const monthNumbers = generatedMonthNumbers; export const weekNumbers = generatedWeekNumbers; export const dayNumbers = generatedDayNumbers; export const quarterhourNumbers = generatedQuarterhourNumbers; export const ordinalDayNumbers = generatedOrdinalDayNumbers; export const hourNumbers = generatedHourNumbers; export const minuteNumbers = generatedMinuteNumbers; export const secondNumbers = generatedSecondNumbers; export const mockDateObject = generatedMockDateObject; export const dimensionDurations = ['years', 'months', 'weeks', 'days', 'hours', ]; export const flattenDelimiter = '+=+'; export function getOpenHour(options = {}): BooleanAnswer { return 1; /* //TODO: fix this const { date, parsedDate, zone, } = options; const entity = this.entity || {}; const dimension = this.dimension; const operations = entity.operations; const closed = 0; const opened = 1; let openFromCustomClosed = 1; let openFromCustomOpened = 0; if (!operations) throw new Error(`${entity.name} is missing operation details`); if (!operations.launch_date) throw new Error(`${entity.name} is missing a launch date`); if (!operations.is_24_hours && (!operations.business_hours || Object.keys(operations.business_hours).length<7)) throw new Error(`${entity.name} is missing business hours`); if (operations.override && operations.override.hours && operations.override.hours.closed_times) { operations.override.hours.closed_times.forEach(closed => { const closedStart = luxon.DateTime.fromISO(closed.close_start, { zone, }).toJSDate(); const closedEnd = luxon.DateTime.fromISO(closed.close_end, { zone, }).toJSDate(); if (date >= closedStart && date < closedEnd) { openFromCustomClosed = 0; return closed; } }); } if (operations.business_hours) { let regular_closed = 0; if (dimension === 'hourly') { if (parsedDate.weekday === 1 && isClosedOnDay({ weekday: 1, dayname: 'monday', parsedDate, date, operations, zone, })) regular_closed = 1; if (parsedDate.weekday === 2 && isClosedOnDay({ weekday: 2, dayname: 'tuesday', parsedDate, date, operations, zone, })) regular_closed = 1; if (parsedDate.weekday === 3 && isClosedOnDay({ weekday: 3, dayname: 'wednesday', parsedDate, date, operations, zone, })) regular_closed = 1; if (parsedDate.weekday === 4 && isClosedOnDay({ weekday: 4, dayname: 'thursday', parsedDate, date, operations, zone, })) regular_closed = 1; if (parsedDate.weekday === 5 && isClosedOnDay({ weekday: 5, dayname: 'friday', parsedDate, date, operations, zone, })) regular_closed = 1; if (parsedDate.weekday === 6 && isClosedOnDay({ weekday: 6, dayname: 'saturday', parsedDate, date, operations, zone, })) regular_closed = 1; if (parsedDate.weekday === 7 && isClosedOnDay({ weekday: 7, dayname: 'sunday', parsedDate, date, operations, zone, })) regular_closed = 1; } // if (operations.custom_times) { if (operations.override && operations.override.hours && operations.override.hours.custom_times) { operations.override.hours.custom_times.forEach(open => { const openStart = luxon.DateTime.fromISO(open.custom_open, { zone, }).toJSDate(); const openEnd = luxon.DateTime.fromISO(open.custom_close, { zone, }).toJSDate(); if (date >= openStart && openEnd) { // console.log('custom open date'); openFromCustomOpened = 1; regular_closed = opened; return opened; } }); } if (regular_closed === 1) return closed; } return (openFromCustomClosed && opened) || openFromCustomOpened; */ } export function getIsOutlier(this: { data: ModelXDataTypes.Data; datum: ModelXDataTypes.Datum; }, { outlier_property, }: { outlier_property?: string; } = {}): BooleanAnswer { if (outlier_property) { const data = this.data; const outlier = Outlier(data.map(datum => datum[ outlier_property ])); const datum = this.datum; const dataPoint = datum[ outlier_property ]; return outlier.testOutlier(dataPoint) ? 1 : -1; } else { return 0; } } export function addMockDataToDataSet(DataSet: ModelXDataTypes.DataSet, { mockEncodedData = [], includeConstants = true, }: { mockEncodedData?: ModelXDataTypes.Data; includeConstants?: boolean; }) { const newMockData = new Array().concat(mockEncodedData, includeConstants ? mockDates : []); DataSet.data = DataSet.data.concat(newMockData); return DataSet; } export function removeMockDataFromDataSet(DataSet:ModelXDataTypes.DataSet, { mockEncodedData = [], includeConstants = true, }: { mockEncodedData?: ModelXDataTypes.Data; includeConstants?: boolean; }) { const newMockData = new Array().concat(mockEncodedData, includeConstants ? mockDates : []); DataSet.data.splice(DataSet.data.length - newMockData.length, newMockData.length); return DataSet; } export function removeEvaluationData(evaluation:ModelXDataTypes.Datum) { evaluation.actuals = undefined; delete evaluation.actuals; evaluation.estimates = undefined; delete evaluation.estimates; return evaluation; }