 ;; deseasonalize the data, which is reflected below.  It would be a
 ;; good and feasible (easy) bonus to utilize the reliability data.
 
-(defn short-trend
-  "`short-trend` will find the greatest OLS drop over a timeseries `ts`
-  given sub-timeseries of length `long-block`.  The drops are smoothed
-  by a moving average window of length `window`."
-  ([long-block window ts]
-     (short-trend ts [] long-block window))
-  ([long-block window ts reli-ts]
-     (->> (deseasonalize ts)
-          (windowed-apply ols-coefficient long-block)
-          (windowed-apply coll-avg window)
-          (make-monotonic min))))
+;; (defn short-trend
+;;   "`short-trend` will find the greatest OLS drop over a timeseries `ts`
+;;   given sub-timeseries of length `long-block`.  The drops are smoothed
+;;   by a moving average window of length `window`."
+;;   ([long-block window ts]
+;;      (short-trend ts [] long-block window))
+;;   ([long-block window ts reli-ts]
+;;      (->> (deseasonalize ts)
+;;           (windowed-apply ols-coefficient long-block)
+;;           (windowed-apply coll-avg window)
+;;           (make-monotonic min))))
 
 (defn collect-short-trend
   "preps the short-term drop for the merge into the other data by separating

(ns forma.trends.analysis
  (:use [forma.matrix.utils :only (variance-matrix coll-avg)]
        [clojure.math.numeric-tower :only (sqrt floor abs)]
        [forma.trends.filter :only (deseasonalize make-reliable hp-filter)])
  (:require [forma.utils :as utils]
            [incanter.core :as i]
            [incanter.stats :as s]))

;; The first few functions are more general, and could be pulled into,
;; say, the matrix operation namespace.  For now, we will leave them
;; here, until we can talk more about what goes into that namespace.

(defn time-trend-cofactor
  "construct a matrix of cofactors; first column is comprised of ones,
  second column is a range from 1 to [num-months].  The result is a
  [num-months]x2 incanter matrix."
  [num-months]
  (i/trans (i/bind-rows (repeat num-months 1)
                        (range 1 (inc num-months)))))

(defn singular?
  "Check to see if the supplied matrix `X` is singular. note that `X`
  has to be square, n x n, where n > 1."
  [X]
  (<= (i/det X) 0))

(defn ols-coefficient
  "extract OLS coefficient from a time-series."
  [ts]
  (let [ycol (i/trans [ts])
        X (time-trend-cofactor (count ts))]
    (i/sel (i/mmult (variance-matrix X)
                    (i/trans X)
                    ycol)
           1 0)))

(defn windowed-apply 
  "apply a function [f] to a window along a sequence [xs] of length [window]"
  [f window xs]
  (pmap f (partition window 1 xs)))

(defn make-monotonic
  "move through a collection `coll` picking up the min or max values, depending
  on the value of `comparator` which can be either `min` or `max`.  This is very
  similar, I think, to the `reduce` function, but with side effects that print
  into a vector."
  [comparator coll]
  (reduce (fn [acc val]
            (conj acc
                  (if (empty? acc)
                    val
                    (comparator val (last acc)))))
          []
          coll))

;; ## WHOOPBANG :: Collect the short-term drop associated with a
;; ## time-series

               product
               (vector product)))))

;; (defn outer-product
;;   " calculate the outer product of two vectors

;;   Example:
;;   (outer-product [1 2 3] [1 2 3])
;;   => [1.0000 2.0000 3.0000
;;       2.0000 4.0000 6.0000
;;       3.0000 6.0000 9.0000]
;; "
;;   [v1 v2]
;;   (i/matrix
;;    (for [e v1] (vec (map (partial * e) v2)))))


(defn lengthening-mat
