- Index
- »
- docHaxall
- »
- Axon Usage
Axon Usage
Str Examples
Common functions for working with strings: capitalize()
, contains()
, decapitalize()
, endsWith()
, get()
, index()
, indexr()
, isEmpty()
, isTagName()
, lower()
, replace()
, size()
, startsWith()
, toTagName()
, trim()
, trimStart()
, trimEnd()
, upper()
.
123.toStr >> "123" // convert any object to string "num=" + 3 >> "num=3" // use '+' for concat "hi world".isEmpty >> false "hi world".size >> 8 "hi world"[5] >> 114 // unicode char for 'w' "hi world"[3..-2] >> "worl" // get with range is slice "root toot".index("oo") >> 1 "root toot".indexr("oo") >> 6 "hi world".contains("hi") >> true "Abc".upper >> "ABC" "Abc".lower >> "abc" "a,b,c".split(",") >> ["a", "b", "c"] "fooBar".capitalize >> "FooBar" "FooBar".decapitalize >> "fooBar" " xyz ".trim >> "xyz" "abcd".startsWith("ab") >> true "abcd".endsWith("cd") >> true "foo bar".isTagName >> false "foo bar".toTagName >> "fooBar" "root toot".replace("oo", "a") >> "rat tat"
Date/Time Examples
Common functions for working with Dates, Times, and DateTimes: date()
, dateTime()
, day()
, dayOfYear()
, dst()
, firstOfMonth()
, fromJavaMillis()
, hour()
, isLeapYear()
, isWeekday()
, isWeekend()
, lastOfMonth()
, minute()
, month()
, now()
, nowTicks()
, numDaysInMonth()
, second()
, startOfWeek()
, time()
, toJavaMillis()
, toTimeZone()
, today()
, tz()
, weekOfYear()
, weekday()
, year()
, yesterday()
.
now() >> current DateTime in local timezone today() >> today's Date in local timezone yesterday() >> yesterday's Date in local timezone today() + 1day >> tomorrow today() + 7day >> next week now() + 1hr >> one hour from now dateTime(2023-03-14, 0:00, "New_York") >> create DateTime from Date, Time, and timezone now().date >> Date portion of DateTime now().time >> Time portion of DateTime now().tz >> timezone string name of DateTime today().year >> four digit year today().month >> month as number between 1 and 12 today().day >> day of month as number between 1 and 31 now().hour >> hour as number between 0 and 23 now().minute >> minutes as number between 0 and 59 now().second >> seconds as number between 0 and 59 today().weekday >> day of week as number between 0 and 6 today().isWeekend >> true if Sunday/Saturday today().isWeekday >> true if Monday - Friday today().firstOfMonth >> first Date of the month today().lastOfMonth >> last Date of the month now().toTimeZone("UTC") >> convert DateTime to different timezone today().numDaysInMonth >> number of days in Date's month isLeapYear(2024) >> is a leap year now().dst >> is DateTime in daylight saving time today().dayOfYear >> number 1 to 366 today().weekOfYear >> number 1 to 53 startOfWeek() >> 0 for Sun or 1 for Mon based on locale now().toJavaMillis >> milliseconds since Unix epoch of 1970 now().toJavaMillis.fromJavaMillis >> convert back to DateTime
Date Spans
Common functions for working with Spans and DateSpans: eachDay()
, eachMonth()
, end()
, lastMonth()
, lastQuarter()
, lastWeek()
, lastYear()
, numDays()
, pastMonth()
, pastWeek()
, pastYear()
, start()
, thisMonth()
, thisQuarter()
, thisWeek()
, thisYear()
, toDateSpan()
, toSpan()
, today()
, yesterday()
.
today() >> any Date value may be used span thisWeek() >> DateSpan for current week (locale based start of week) thisMonth() >> DateSpan for current month thisQuarter() >> DateSpan for current quarter thisYear() >> DateSpan for current year pastWeek() >> DateSpan for previous 7 days pastMonth() >> DateSpan for previous 30 days pastYear() >> DateSpan for previous 365 days lastWeek() >> DateSpan for last week (locale based start of week) lastMonth() >> DateSpan for last month lastQuarter() >> DateSpan for last quarter lastYear() >> DateSpan for last year toDateSpan(2023-01-01..2023-02-28) >> DateSpan with two explicit dates toDateSpan(2023-02-14) >> DateSpan for a day toDateSpan(2023-02) >> DateSpan for a month toDateSpan(2023) >> DateSpan for a year toDateSpan(2023-02).toSpan >> Convert DateSpan to Span toDateSpan(2024-02).start >> First day of DateSpan toDateSpan(2024-02).end >> Last day of DateSpan toDateSpan(2024-02).numDays >> Number of days in DateSpan eachDay(2024-02) (d) => echo(d) >> Iterate the Dates in a DateSpans eachMonth(2024) (d) => echo(d) >> Iterate the months in a DateSpan
Uri Examples
Common functions for working with URIs: uriBasename()
, uriDecode()
, uriEncode()
, uriExt()
, uriHost()
, uriIsDir()
, uriName()
, uriPath()
, uriPathStr()
, uriPort()
, uriScheme()
`/a/b/file.txt`.uriName >> "file.txt" `/a/b/file.txt`.uriBasename >> "file" `/a/b/file.txt`.uriExt >> "txt" `http://host:81/a/b/file.txt`.uriScheme >> "http" `http://host:81/a/b/file.txt`.uriHost >> "host" `http://host:81/a/b/file.txt`.uriPort >> 81 `http://host:81/a/b/file.txt`.uriPathStr >> "/a/b/file.txt" `http://host:81/a/b/file.txt`.uriPath >> ["a", "b", "file.txt"] `/a/b`.uriIsDir >> false `/a/b/`.uriIsDir >> true `file name.html`.uriEncode >> "file%20name.html" "file%20name.html".uriDecode >> `file name.html`
List Examples
Common functions for working with lists: add()
, addAll()
, all()
, any()
, concat()
, contains()
, get()
, each()
, find()
, findAll()
, first()
, flatMap()
, fold()
, index()
, indexr()
, insert()
, insertAll()
, isEmpty()
, last()
, map()
, moveTo()
, remove()
, set()
, size()
, sort()
, sortr()
, unique()
.
x: [10, 20, 30] y: ["chat", "apple", "bee"] x.isEmpty >> false x.size >> 3 x[2] >> 30 x[1..-1] >> [20, 30] // get with range is slice x.first >> 10 x.index(30) >> 2 x.index(40) >> null x.contains(20) >> true x.fold(sum) >> 60 x.any v => v < 20 >> true x.all v => v < 20 >> false x.concat(";") >> "10;20;30"
Functions which modify a list always return a new list (the original is immutable):
x.add(40) >> [10, 20, 30, 40] x.addAll([40, 50]) >> [10, 20, 30, 40, 50] x.set(2, 99) >> [10, 20, 99] x.insert(0, 99) >> [99, 10, 20, 30] x.insertAll(0, [88,99]) >> [88, 99, 10, 20, 30] x.remove(1) >> [10, 30] y.sort >> ["apple", "bee", "chart"] y.sortr >> ["chart", "bee", "apple"] y.sort((a,b)=>a.size<=>b.size) >> ["bee", "chat", "apple"] y.each s => echo(s) >> iterator y.map s => s.size >> [4, 5, 3] y.flatMap s => [s, s.size] >> ["chat", 4, "apple", 5, "bee", 3] y.find s => s.size == 3 >> "bee" y.findAll s => s.size <= 4 >> ["chat", "bee"] y.moveTo("chat", -1) >> ["apple", "bee", "chat"] [1,1,1,2].unique >> [1,2]
Dict Examples
Common functions for working with dicts: all()
, any()
, get()
, each()
, find()
, findAll()
, has()
, isEmpty()
, map()
, missing()
, names()
, remove()
, set()
, dis()
, trap()
, vals()
.
d: {dis:"Bob", bday:1980-06-01} d.isEmpty >> false d["bday"] >> 1980-06-01 d["foo"] >> null d->dis >> "Bob" d->foo >> UnknownNameErr exception d.has("bday") >> true d.missing("bday") >> false d.names >> ["dis", "bday"] d.vals >> ["Bob", 1980-06-01] d.dis >> "Bob" d.dis("bday") >> "1-Jun-1980" d.any v => v.isDate >> true d.all(isDate) >> false // iterate keys, vals d.each((v, k) => echo(k + ": " + v))
For a detailed discussion on using []
versus ->
see Axon Language.
Functions which modify a dict always return a new dict (the original is immutable):
d.set("person", marker()) >> {dis:"Bob", bday:1980-06-01, person} d.remove("bday") >> {dis:"Bob"} d.map v => v + "!" >> {dis:"Bob!", bday:"1980-06-01!"} d.find v => v.isDate >> 1980-06-01 d.findAll v => v.isDate >> {bday:1980-06-01}
Grid Examples
Common functions for working with grids: addCol()
, addColMeta()
, addMeta()
, addRow()
, addRows()
, all()
, any()
, col()
, cols()
, colNames()
, colToList()
, each()
, find()
, findAll()
, first()
, flatMap()
, foldCol()
, foldCols()
, get()
, gridRowsToDict()
, gridColsToDict()
, has()
, isEmpty()
, join()
, joinAll()
, keepCols()
, last()
, map()
, meta()
, missing()
, removeCol()
, removeCols()
, renameCol()
, reorderCols()
, rowToList()
, size()
, sort()
, sortr()
, toGrid()
, unique()
.
// create grid from list of dicts g: [{dis:"Site-A", area:2300ft²}, {dis:"Site-B", area:3100ft²}, {dis:"Site-C", area:1950ft²}].toGrid g.isEmpty >> false g.size >> 3 g.has("area") >> true g.missing("foo") >> true g.meta >> grid level meta data g.cols >> [ Col("dis"), Col("area") } g.colNames >> ["dis", "area"] g.col("dis").name >> "dis" g.col("dis").meta >> meta data for column "dis" g.col("foo") >> throws UnknownNameErr g.col("foo", false) >> null g.colToList("area") >> [2300ft², 3100ft², 1950ft²] g.first >> {dis:"Site-A", area:2300ft²} g.last >> {dis:"Site-C", area:1950ft²} g[1] >> {dis:"Site-B", area:3100²} g[-2] >> {dis:"Site-B", area:3100²} g[0..1] >> slice to new grid of Site-A, Site-B g.each(row=>...) >> iterate each row as a dict g.foldCol("area", sum) >> 7350ft² g.any r => r->area > 2000ft² >> true g.all r => r->area > 2000ft² >> false
Functions which modify a grid always return a new grid (the original is immutable):
g.sort("area") >> sort by area column g.sortr("area") >> reverse sort by area column g.sort((a,b)=>...) >> sort with function g.map r => r.set("area", r->area.to(1m²)) >> area ft² -> m² g.find r => r->dis == "Site-A" >> find row where dis == "Site-A" g.findAll r => r->area < 2000 >> grid with rows where area < 2000 rowToName: (r) => r->dis[-1..-1].lower >> func to map "Site-A" -> "a" g.gridRowsToDict(rowToName, r=>r->area) >> {a:2300ft², b:3100², c: 1950ft²} g.gridColsToDict(c=>c.name,c=>c.name.size) >> {dis:3, area:4} g.addMeta({title:"Sites"}) >> adds grid level meta data g.addColMeta("area", {dis:"Sq Footage"}) >> add column level meta data g.addCol("areaM2") r => r->area.to(1m²) >> add new column which is area in m² g.renameCol("area", "sqFt") >> rename column area -> sqFt g.reorderCols(["dis", "area"]) >> force specific column ordering g.removeCol("area") >> remove a column g.removeCols(["area"]) >> remove a list of columns g.keepCols(["dis"]) >> remove all cols except given list g.addRow({dis:"Site-D", area: 4000ft²}) >> add new row to end of grid g.addRows([{dis:"Site-D"},{dis:"Site-E"}]) >> add list of new rows to grid g.unique("dis") >> grid with rows with unique values in dis col
Joins between two grids may be done by column name using join()
or joinAll()
:
// create another grid h: [{dis:"Site-A", tz:"Chicago"}, {dis:"Site-B", tz:"Denver"}, {dis:"Site-C", tz:"New_York"}].toGrid // join g and h by the dis column g.join(h, "dis") // resulting join grid dis area tz ------ -------- -------- Site-A 2,300ft² Chicago Site-B 3100ft² Denver Site-C 1,950ft² New_York
Regex Examples
Regular expressions can be used via the reMatches()
, reFind()
, reFindAll()
, and reGroups()
functions. Typically you will want to use raw string literals r""
to avoid escaping the backslash:
// check match for entire string reMatches(r"AHU-(\d+)", "AHU") // false reMatches(r"AHU-(\d+)", "AHU-10") // true // find substring in a regex reFind(r"AHU-(\d+)", "Store-2") // null reFind(r"AHU-(\d+)", "Store-2 AHU-3") // "AHU-3" // find all substring groups in a regex reGroups(r"(Clg|Hgt)-(\d+)", "foo") // null reGroups(r"(Clg|Hgt)-(\d+)", "Hgt-7") // ["Hgt-7", "Hgt", "7"] reGroups(r"(Clg|Hgt)-(\d+)", "<Hgt-7>") // ["Hgt-7", "Hgt", "7"]
Note that reGroups()
returns a list of strings for each group defined by ()
. The first item in the list is always the entire match.
Axon uses the Java regular expression engine - see java.util.regex.Pattern for full specification.
Read Examples
You can do simple queries to slice and dice your data:
site // find everything with site tag site and geoCity=="Richmond" // find all the sites in Richmond equip and siteRef==xxxx // find all the equip within a site with rec id xxx equip and siteRef->dis=="Foo" // find all the equip within a site with dis tag "Foo" ahu and siteRef==xxxx // find all the AHUs within a site point and equipRef==xxx // find all the points within a piece of equipment
The above queries are shorthand for readAll(filter)
. In general most queries will start will some filter to select a set of recs from the database.
His Examples
To perform time-series analysis you'll typically pipe one or more records to the hisRead() function (SkySpark only):
// get history data for the points within a given piece of equipment readAll(point and equipRef==xxx).hisRead(2009-10-03) // for a single day readAll(point and equipRef==xxx).hisRead(2009-10) // for a month readAll(point and equipRef==xxx).hisRead(2009) // for an entire year readAll(point and equipRef==xxx).hisRead(pastWeek) // for last 7 days readAll(point and equipRef==xxx).hisRead(today) // for today readAll(point and equipRef==xxx).hisRead(2009-10-01..2009-10-07)
Any of the time range functions can be used with hisRead() including today()
, yesterday()
, thisWeek()
, pastWeek()
, thisMonth()
, pastMonth()
.
In general once you get above a days worth of data, you will need to use a rollup to condense the data into a more manageable volume. Rollups are easy:
// find daily max of electrical demand for month of March 2010 readAll(kw).hisRead(2010-03).hisRollup(max, 1day)
As you start to perform time-series analysis, you'll start to to use functions to map, filter, and fold your data:
// find all the days where daily max exceeded 200 KW readAll(kw).hisRead(2010-03).hisRollup(max, 1day).hisFindAll(v => v > 200) // find all the periods of time where zone temp was above 75 readAll(zoneTemp).hisRead(pastMonth).hisFindPeriods(v => v > 75)
As you start to write functions that mine the data for certain patterns, you'll want to start combining them. A common technique is to use hisFindPeriods
to find different conditions, then compute the intersection:
(ahu, dates) => do // find periods in cooling mode for this AHU coolPeriods: read(cool and equipRef==ahu->id) .hisRead(dates).hisFindPeriods(v => v) // find periods in heating mode for this AHU heatPeriods: read(heat and equipRef==ahu->id) .hisRead(dates).hisFindPeriods(v => v) // compute when AHU running in both heating and cooling modes hisPeriodIntersection([coolPeriods, heatPeriods]) end
Def Examples
Common functions for working with defs: conjuncts()
, def()
, defs()
, tags()
, terms()
:
def(^site) // lookup def for site tag def("site") // convenience for site(^site) defs() // list all definitions tags() // list only tag definitions
Pivot Examples
The pivot() and xqPivot() functions are used to transform a grid or list of dicts into a pivot table. Pivot tables are used to summarize data based on grouping and rolling up of cell values. These functions are only available in SkySpark.
We use a dict called the shape to define how the generate the pivot table:
- rows: selection to use for row grouping
- cols: selection to use for column grouping
- cells: selection and folding function to use for rollups
Selection is a dotted path of tag names with special handling for marker/ref tags. For example "targetRef.site" will select the site id of any target type. If the target has the site marker tag, then its the target id itself, otherwise its the value of siteRef.
All the shape tags (rows, cols, cells) may be a single Dict or a list of Dicts. The dicts must have the select
tag with the selector.
Row and col groupings are used to group the rollups by their unique combinations. For example the group [geoState, geoCity]
would create a grouping for every unique combination of the geoState and geoCity tags. Any input row missing one of the group's selectors is implicitly skipped in the result.
Row grouping is used to define the summarized rows in the resulting grid. At least one row group tag must be defined. Column grouping is used to create a column in the result for each unique column group.
Cells define which tag to rollup for a given grouping. A default folding function is used based on the selected tag's name. An explicit folding function may be specified with the fold
tag. The following folding names are supported:
sum
: Numbersmin
: Numbersmax
: Numbersavg
: Numberscount
: AnythingperiodUnion
: Str base64 periods, must also have date column
Our examples all use this input grid:
geoState, geoCity, dur, cost "VA", "Richmond", 10h, 40$ "VA", "Richmond", 4h, 12$ "VA", "Richmond", 2h, 6$ "VA", "Norfolk", 8h, 8$ "VA", "Norfolk", 11h, 7$ "CA", "Richmond", 3h, 5$ "CA", "Richmond", 4h, 4$
A simple pivot which rolls up dur and cost by geoState:
pivot(input, { rows: {select:"geoState"}, cells: [{select:"cost"}, {select:"dur"}] }) geoState, cost, dur "CA", 9$, 7h "VA", 73$, 35h
A pivot which folds cost by avg, min, and max:
pivot(input, { rows: {select:"geoState"}, cells: [{select:"cost", fold:"avg"}, {select:"cost", fold:"max"}, {select:"cost", fold:"min"}] }) geoState, cost_avg, cost_max, cost_min "CA", 4.5$, 5$, 4$ "VA", 14.6$, 40$, 6$
Pivot using two tags for row grouping:
pivot(input, { rows: [{select:"geoState"}, {select:"geoCity"}], cells: {select:"dur"} }) geoState, geoCity, dur "CA", "Richmond", 7h "VA", "Norfolk", 19h "VA", "Richmond", 16h
Pivot using a column grouping:
pivot(input, { rows: {select:"geoState"}, cols: {select:"geoCity"}, cells: {select:"dur"} }) geoState, Norfolk dur, Richmond dur "CA", null, 7hr "VA", 19hr, 16hr
The dicts used for row, col, and cells are passed thru into the column meta of the resulting grid.
Energy Examples
Most energy queries start life using a read/readAll piped to the hisRead function:
// daily consumption data for all sites in Mar 2011 readAll(energy and siteMeter).hisRead(2011-03).hisRollup(sum, 1day) // monthly consumption data for all sites in 2010 readAll(energy and siteMeter).hisRead(2010).hisRollup(sum, 1mo) // raw demand data for all sites on 1 Apr 2011 readAll(power and siteMeter).hisRead(2011-04-01) // demand data normalized by area (square footage/meters) readAll(power and siteMeter).hisRead(2011-04-01) .energyNormByArea // demand data normalized by degree-day readAll(power and siteMeter).hisRead(2011-04-01) .energyNormByDegreeDay // demand data normalized by area and degree-day readAll(power and siteMeter).hisRead(2011-04-01) .energyNormByArea .energyNormByDegreeDay // table of site dis and total kWh consumption for March sorted by kWh readAll(energy and siteMeter).hisRead(2011-03) .hisRollup(sum, 1mo) .hisFlatten((kw,ts,his) => { dis:his->siteRef->dis, kw:kw }) .sort("kw") // average daily profile of hourly demand peak across last month readAll(power and siteMeter).hisRead(lastMonth) .hisRollup(max, 1hr) .hisDailyProfile(avg)