{"action":"created","comment":{"url":"https://api.github.com/repos/numenta/numenta-apps/pulls/comments/36572350","id":36572350,"diff_hunk":"@@ -0,0 +1,289 @@\n+# ----------------------------------------------------------------------\n+# Numenta Platform for Intelligent Computing (NuPIC)\n+# Copyright (C) 2015, Numenta, Inc.  Unless you have purchased from\n+# Numenta, Inc. a separate commercial license for this software code, the\n+# following terms and conditions apply:\n+#\n+# This program is free software: you can redistribute it and/or modify\n+# it under the terms of the GNU General Public License version 3 as\n+# published by the Free Software Foundation.\n+#\n+# This program is distributed in the hope that it will be useful,\n+# but WITHOUT ANY WARRANTY; without even the implied warranty of\n+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n+# See the GNU General Public License for more details.\n+#\n+# You should have received a copy of the GNU General Public License\n+# along with this program.  If not, see http://www.gnu.org/licenses.\n+#\n+# http://numenta.org/licenses/\n+# ----------------------------------------------------------------------\n+\n+\"\"\"\n+Implements Unicorn's model interface.\n+\"\"\"\n+\n+\n+from datetime import datetime\n+import json\n+import logging\n+from optparse import OptionParser\n+import sys\n+\n+import numpy\n+\n+from nupic.data import fieldmeta\n+from nupic.frameworks.opf.modelfactory import ModelFactory\n+\n+\n+# TODO: can we reuse htmengine primitives here?\n+from htmengine.algorithms.modelSelection.clusterParams import (\n+  getScalarMetricWithTimeOfDayParams)\n+from htmengine.runtime.scalar_metric_utils import (\n+  MODEL_CREATION_RECORD_THRESHOLD)\n+\n+\n+g_log = logging.getLogger(__name__)\n+\n+\n+\n+class _Options(object):\n+\n+  def __init__(self, modelId):\n+    \"\"\"\n+    :param str modelId: model identifier\n+    \"\"\"\n+    self.modelId = modelId\n+\n+\n+\n+def _parseArgs():\n+  \"\"\" Parse command-line args\n+\n+  :rtype: _Options object\n+  \"\"\"\n+  helpString = (\n+    \"%prog [options]\\n\\n\"\n+    \"Start Unicorn Engine that runs a single model.\")\n+\n+  parser = OptionParser(helpString)\n+\n+  parser.add_option(\n+    \"--model\",\n+    action=\"store\",\n+    type=\"string\",\n+    dest=\"modelId\",\n+    help=\"Model id string\")\n+\n+\n+  options, positionalArgs = parser.parse_args()\n+\n+  if len(positionalArgs) != 0:\n+    msg = (\"Command accepts no positional args\")\n+    g_log.error(msg)\n+    parser.error(msg)\n+\n+  if not options.modelId:\n+    msg = (\"Missing or empty model id\")\n+    g_log.error(msg)\n+    parser.error(msg)\n+\n+\n+  return _Options(modelId=options.modelId)\n+\n+\n+\n+class _Anomalizer(object):\n+  \"\"\" This class is responsible for anomaly likelihood processing\n+\n+  NOTE: consider modifying htmengine's anomaly_likelihood_helper.py so that we\n+  can share it with htmengine's Anomaly Service\n+\n+\n+  TODO Flesh me out\n+  \"\"\"\n+\n+  def process(self, timestamp, metricValue, rawAnomalyScore):\n+    \"\"\" Perform anomaly likelihood processing\n+\n+    :param datetime.datetime timestamp: metric data sample's timestamp\n+    :param number metricValue: scalar value of metric data sample; float or int\n+    :param float rawAnomalyScore: raw anomaly score computed by NuPIC model\n+\n+    :returns: anomaly likelihood value\n+    :rtype: float\n+    \"\"\"\n+    pass\n+\n+\n+\n+class _ModelRunner(object):\n+  \"\"\" Use OPF Model to process metric data samples from stdin and and emit\n+  anomaly likelihood results to stdout\n+  \"\"\"\n+\n+  # Input column meta info compatible with parameters generated by\n+  # getScalarMetricWithTimeOfDayParams\n+  # of htmengine.algorithms.selection.clusterParams\n+  _INPUT_RECORD_SCHEMA = (\n+    fieldmeta.FieldMetaInfo(\"c0\", fieldmeta.FieldMetaType.datetime,\n+                            fieldmeta.FieldMetaSpecial.timestamp),\n+    fieldmeta.FieldMetaInfo(\"c1\", fieldmeta.FieldMetaType.float,\n+                            fieldmeta.FieldMetaSpecial.none),\n+  )\n+\n+\n+  # minimum resolution of metric; used to set up encoders; if None,\n+  # getScalarMetricWithTimeOfDayParams will apply its default.\n+  #\n+  # TODO: is default acceptable?\n+  _MIN_METRIC_RESOLUTION = None\n+\n+\n+  def __init__(self, modelId):\n+    self._modelId = modelId\n+    self._model = None\n+    self._anomalizer = _Anomalizer()","path":"unicorn/engine/engine.py","position":146,"original_position":146,"commit_id":"3c9fa3706d800c99ca42e12d08279e2338802dfc","original_commit_id":"3c9fa3706d800c99ca42e12d08279e2338802dfc","user":{"login":"oxtopus","id":326528,"avatar_url":"https://avatars.githubusercontent.com/u/326528?v=3","gravatar_id":"","url":"https://api.github.com/users/oxtopus","html_url":"https://github.com/oxtopus","followers_url":"https://api.github.com/users/oxtopus/followers","following_url":"https://api.github.com/users/oxtopus/following{/other_user}","gists_url":"https://api.github.com/users/oxtopus/gists{/gist_id}","starred_url":"https://api.github.com/users/oxtopus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/oxtopus/subscriptions","organizations_url":"https://api.github.com/users/oxtopus/orgs","repos_url":"https://api.github.com/users/oxtopus/repos","events_url":"https://api.github.com/users/oxtopus/events{/privacy}","received_events_url":"https://api.github.com/users/oxtopus/received_events","type":"User","site_admin":false},"body":"Does this need to be an instance property?","created_at":"2015-08-08T00:40:07Z","updated_at":"2015-08-08T00:40:07Z","html_url":"https://github.com/numenta/numenta-apps/pull/194#discussion_r36572350","pull_request_url":"https://api.github.com/repos/numenta/numenta-apps/pulls/194","_links":{"self":{"href":"https://api.github.com/repos/numenta/numenta-apps/pulls/comments/36572350"},"html":{"href":"https://github.com/numenta/numenta-apps/pull/194#discussion_r36572350"},"pull_request":{"href":"https://api.github.com/repos/numenta/numenta-apps/pulls/194"}}},"pull_request":{"url":"https://api.github.com/repos/numenta/numenta-apps/pulls/194","id":41944107,"html_url":"https://github.com/numenta/numenta-apps/pull/194","diff_url":"https://github.com/numenta/numenta-apps/pull/194.diff","patch_url":"https://github.com/numenta/numenta-apps/pull/194.patch","issue_url":"https://api.github.com/repos/numenta/numenta-apps/issues/194","number":194,"state":"open","locked":false,"title":"ENG-12 Created Unicorn back-end design via realistic pseudocode.","user":{"login":"vitaly-krugl","id":1441066,"avatar_url":"https://avatars.githubusercontent.com/u/1441066?v=3","gravatar_id":"","url":"https://api.github.com/users/vitaly-krugl","html_url":"https://github.com/vitaly-krugl","followers_url":"https://api.github.com/users/vitaly-krugl/followers","following_url":"https://api.github.com/users/vitaly-krugl/following{/other_user}","gists_url":"https://api.github.com/users/vitaly-krugl/gists{/gist_id}","starred_url":"https://api.github.com/users/vitaly-krugl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vitaly-krugl/subscriptions","organizations_url":"https://api.github.com/users/vitaly-krugl/orgs","repos_url":"https://api.github.com/users/vitaly-krugl/repos","events_url":"https://api.github.com/users/vitaly-krugl/events{/privacy}","received_events_url":"https://api.github.com/users/vitaly-krugl/received_events","type":"User","site_admin":false},"body":"This is an incomplete prototypical implementation of the Unicorn \"Python Engine\" that demonstrates the proposed design.","created_at":"2015-08-08T00:15:13Z","updated_at":"2015-08-08T00:40:07Z","closed_at":null,"merged_at":null,"merge_commit_sha":"cca6f9ccbecc68e220fd71d68625ee3e9f9b8bfa","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/numenta/numenta-apps/pulls/194/commits","review_comments_url":"https://api.github.com/repos/numenta/numenta-apps/pulls/194/comments","review_comment_url":"https://api.github.com/repos/numenta/numenta-apps/pulls/comments{/number}","comments_url":"https://api.github.com/repos/numenta/numenta-apps/issues/194/comments","statuses_url":"https://api.github.com/repos/numenta/numenta-apps/statuses/3c9fa3706d800c99ca42e12d08279e2338802dfc","head":{"label":"vitaly-krugl:eng12-unicorn-backend-design","ref":"eng12-unicorn-backend-design","sha":"3c9fa3706d800c99ca42e12d08279e2338802dfc","user":{"login":"vitaly-krugl","id":1441066,"avatar_url":"https://avatars.githubusercontent.com/u/1441066?v=3","gravatar_id":"","url":"https://api.github.com/users/vitaly-krugl","html_url":"https://github.com/vitaly-krugl","followers_url":"https://api.github.com/users/vitaly-krugl/followers","following_url":"https://api.github.com/users/vitaly-krugl/following{/other_user}","gists_url":"https://api.github.com/users/vitaly-krugl/gists{/gist_id}","starred_url":"https://api.github.com/users/vitaly-krugl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vitaly-krugl/subscriptions","organizations_url":"https://api.github.com/users/vitaly-krugl/orgs","repos_url":"https://api.github.com/users/vitaly-krugl/repos","events_url":"https://api.github.com/users/vitaly-krugl/events{/privacy}","received_events_url":"https://api.github.com/users/vitaly-krugl/received_events","type":"User","site_admin":false},"repo":{"id":36960229,"name":"numenta-apps","full_name":"vitaly-krugl/numenta-apps","owner":{"login":"vitaly-krugl","id":1441066,"avatar_url":"https://avatars.githubusercontent.com/u/1441066?v=3","gravatar_id":"","url":"https://api.github.com/users/vitaly-krugl","html_url":"https://github.com/vitaly-krugl","followers_url":"https://api.github.com/users/vitaly-krugl/followers","following_url":"https://api.github.com/users/vitaly-krugl/following{/other_user}","gists_url":"https://api.github.com/users/vitaly-krugl/gists{/gist_id}","starred_url":"https://api.github.com/users/vitaly-krugl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vitaly-krugl/subscriptions","organizations_url":"https://api.github.com/users/vitaly-krugl/orgs","repos_url":"https://api.github.com/users/vitaly-krugl/repos","events_url":"https://api.github.com/users/vitaly-krugl/events{/privacy}","received_events_url":"https://api.github.com/users/vitaly-krugl/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/vitaly-krugl/numenta-apps","description":"HTM based applications and support libraries. Includes Grok for IT Analytics and Grok for Stocks.","fork":true,"url":"https://api.github.com/repos/vitaly-krugl/numenta-apps","forks_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/forks","keys_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/keys{/key_id}","collaborators_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/teams","hooks_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/hooks","issue_events_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/issues/events{/number}","events_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/events","assignees_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/assignees{/user}","branches_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/branches{/branch}","tags_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/tags","blobs_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/git/refs{/sha}","trees_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/git/trees{/sha}","statuses_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/statuses/{sha}","languages_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/languages","stargazers_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/stargazers","contributors_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/contributors","subscribers_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/subscribers","subscription_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/subscription","commits_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/commits{/sha}","git_commits_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/git/commits{/sha}","comments_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/comments{/number}","issue_comment_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/issues/comments{/number}","contents_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/contents/{+path}","compare_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/compare/{base}...{head}","merges_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/merges","archive_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/downloads","issues_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/issues{/number}","pulls_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/pulls{/number}","milestones_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/milestones{/number}","notifications_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/labels{/name}","releases_url":"https://api.github.com/repos/vitaly-krugl/numenta-apps/releases{/id}","created_at":"2015-06-05T23:27:51Z","updated_at":"2015-06-05T23:27:56Z","pushed_at":"2015-08-08T00:13:56Z","git_url":"git://github.com/vitaly-krugl/numenta-apps.git","ssh_url":"git@github.com:vitaly-krugl/numenta-apps.git","clone_url":"https://github.com/vitaly-krugl/numenta-apps.git","svn_url":"https://github.com/vitaly-krugl/numenta-apps","homepage":"http://numenta.com","size":43990,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"numenta:master","ref":"master","sha":"61317b481da4268e1c5d740de2e757b1bc250843","user":{"login":"numenta","id":1039191,"avatar_url":"https://avatars.githubusercontent.com/u/1039191?v=3","gravatar_id":"","url":"https://api.github.com/users/numenta","html_url":"https://github.com/numenta","followers_url":"https://api.github.com/users/numenta/followers","following_url":"https://api.github.com/users/numenta/following{/other_user}","gists_url":"https://api.github.com/users/numenta/gists{/gist_id}","starred_url":"https://api.github.com/users/numenta/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/numenta/subscriptions","organizations_url":"https://api.github.com/users/numenta/orgs","repos_url":"https://api.github.com/users/numenta/repos","events_url":"https://api.github.com/users/numenta/events{/privacy}","received_events_url":"https://api.github.com/users/numenta/received_events","type":"Organization","site_admin":false},"repo":{"id":36754402,"name":"numenta-apps","full_name":"numenta/numenta-apps","owner":{"login":"numenta","id":1039191,"avatar_url":"https://avatars.githubusercontent.com/u/1039191?v=3","gravatar_id":"","url":"https://api.github.com/users/numenta","html_url":"https://github.com/numenta","followers_url":"https://api.github.com/users/numenta/followers","following_url":"https://api.github.com/users/numenta/following{/other_user}","gists_url":"https://api.github.com/users/numenta/gists{/gist_id}","starred_url":"https://api.github.com/users/numenta/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/numenta/subscriptions","organizations_url":"https://api.github.com/users/numenta/orgs","repos_url":"https://api.github.com/users/numenta/repos","events_url":"https://api.github.com/users/numenta/events{/privacy}","received_events_url":"https://api.github.com/users/numenta/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/numenta/numenta-apps","description":"HTM based applications and support libraries. Includes Grok for IT Analytics and Grok for Stocks (code name \"Taurus\").","fork":false,"url":"https://api.github.com/repos/numenta/numenta-apps","forks_url":"https://api.github.com/repos/numenta/numenta-apps/forks","keys_url":"https://api.github.com/repos/numenta/numenta-apps/keys{/key_id}","collaborators_url":"https://api.github.com/repos/numenta/numenta-apps/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/numenta/numenta-apps/teams","hooks_url":"https://api.github.com/repos/numenta/numenta-apps/hooks","issue_events_url":"https://api.github.com/repos/numenta/numenta-apps/issues/events{/number}","events_url":"https://api.github.com/repos/numenta/numenta-apps/events","assignees_url":"https://api.github.com/repos/numenta/numenta-apps/assignees{/user}","branches_url":"https://api.github.com/repos/numenta/numenta-apps/branches{/branch}","tags_url":"https://api.github.com/repos/numenta/numenta-apps/tags","blobs_url":"https://api.github.com/repos/numenta/numenta-apps/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/numenta/numenta-apps/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/numenta/numenta-apps/git/refs{/sha}","trees_url":"https://api.github.com/repos/numenta/numenta-apps/git/trees{/sha}","statuses_url":"https://api.github.com/repos/numenta/numenta-apps/statuses/{sha}","languages_url":"https://api.github.com/repos/numenta/numenta-apps/languages","stargazers_url":"https://api.github.com/repos/numenta/numenta-apps/stargazers","contributors_url":"https://api.github.com/repos/numenta/numenta-apps/contributors","subscribers_url":"https://api.github.com/repos/numenta/numenta-apps/subscribers","subscription_url":"https://api.github.com/repos/numenta/numenta-apps/subscription","commits_url":"https://api.github.com/repos/numenta/numenta-apps/commits{/sha}","git_commits_url":"https://api.github.com/repos/numenta/numenta-apps/git/commits{/sha}","comments_url":"https://api.github.com/repos/numenta/numenta-apps/comments{/number}","issue_comment_url":"https://api.github.com/repos/numenta/numenta-apps/issues/comments{/number}","contents_url":"https://api.github.com/repos/numenta/numenta-apps/contents/{+path}","compare_url":"https://api.github.com/repos/numenta/numenta-apps/compare/{base}...{head}","merges_url":"https://api.github.com/repos/numenta/numenta-apps/merges","archive_url":"https://api.github.com/repos/numenta/numenta-apps/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/numenta/numenta-apps/downloads","issues_url":"https://api.github.com/repos/numenta/numenta-apps/issues{/number}","pulls_url":"https://api.github.com/repos/numenta/numenta-apps/pulls{/number}","milestones_url":"https://api.github.com/repos/numenta/numenta-apps/milestones{/number}","notifications_url":"https://api.github.com/repos/numenta/numenta-apps/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/numenta/numenta-apps/labels{/name}","releases_url":"https://api.github.com/repos/numenta/numenta-apps/releases{/id}","created_at":"2015-06-02T18:49:30Z","updated_at":"2015-08-03T14:32:15Z","pushed_at":"2015-08-08T00:15:14Z","git_url":"git://github.com/numenta/numenta-apps.git","ssh_url":"git@github.com:numenta/numenta-apps.git","clone_url":"https://github.com/numenta/numenta-apps.git","svn_url":"https://github.com/numenta/numenta-apps","homepage":"http://numenta.com","size":45518,"stargazers_count":46,"watchers_count":46,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":34,"mirror_url":null,"open_issues_count":4,"forks":34,"open_issues":4,"watchers":46,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/numenta/numenta-apps/pulls/194"},"html":{"href":"https://github.com/numenta/numenta-apps/pull/194"},"issue":{"href":"https://api.github.com/repos/numenta/numenta-apps/issues/194"},"comments":{"href":"https://api.github.com/repos/numenta/numenta-apps/issues/194/comments"},"review_comments":{"href":"https://api.github.com/repos/numenta/numenta-apps/pulls/194/comments"},"review_comment":{"href":"https://api.github.com/repos/numenta/numenta-apps/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/numenta/numenta-apps/pulls/194/commits"},"statuses":{"href":"https://api.github.com/repos/numenta/numenta-apps/statuses/3c9fa3706d800c99ca42e12d08279e2338802dfc"}}}}