diff --git a/errors/dawn_errors.go b/errors/dawn_errors.go
index 85b1433171ef62179ee05793cc9c4866438a787c..a20d95d21f9e3119746b7147641e8332d7db61c9 100644
--- a/errors/dawn_errors.go
+++ b/errors/dawn_errors.go
@@ -2,9 +2,12 @@ package errors
 
 import (
 	"fmt"
+	"log"
+	"os"
+	"strconv"
+
 	"github.com/gofiber/fiber/v2"
 	"github.com/spf13/viper"
-	"log"
 )
 
 type BaseError interface {
@@ -14,6 +17,7 @@ type BaseError interface {
 type DawnError struct {
 	Name        string `json:"name"`
 	Description string `json:"description"`
+	LogDetails  string `json:"log_details,omitempty"`
 	Code        int    `json:"code"`
 }
 
@@ -38,26 +42,44 @@ func (err *DawnError) BuildStandardError(ctx *fiber.Ctx) StandardError {
 	return StandardError{Source: viper.GetString("app.name"), ErrorCode: err.Name, Description: err.Description, Details: details}
 }
 
+func (err *DawnError) AddLogDetails(logDetails string) *DawnError {
+	err.LogDetails = logDetails
+	return err
+}
+
 func (err *StandardError) LogJson() {
 	log.Println(err)
 }
 
+func (err *DawnError) LogString(c *fiber.Ctx) {
+	requestId := c.Locals("requestId")
+	output := strconv.Itoa(os.Getpid()) + " " + fmt.Sprintf("%s", requestId) + " " + strconv.Itoa(err.Code) + " - " + c.Method() + " " + c.Route().Path + " - " + err.Error() + " - " + err.LogDetails
+	fmt.Println(output)
+}
+
 func INVALID_PRODUCT(passedProduct string) *DawnError {
 	return &DawnError{
-		"INVALID_PRODUCT",
-		"Product type '" + passedProduct + "' is invalid",
-		400,
+		Name:        "INVALID_PRODUCT",
+		Description: "Product type '" + passedProduct + "' is invalid",
+		Code:        400,
 	}
 }
 
 var BAD_REQUEST = &DawnError{
-	"BAD_REQUEST",
-	"Bad request was submitted",
-	400,
+	Name:        "BAD_REQUEST",
+	Description: "Bad request was submitted",
+	Code:        400,
 }
 
 var NO_DATA_FOUND = &DawnError{
-	"NO_DATA_FOUND",
-	"No data found for request",
-	404,
+	Name:        "NO_DATA_FOUND",
+	Description: "No data found for request",
+	Code:        404,
+}
+
+// 500s
+var DATE_PARSE_FAILURE = &DawnError{
+	Name:        "DATE_PARSE_FAILURE",
+	Description: "Date parse failure",
+	Code:        500,
 }
diff --git a/main.go b/main.go
index 536e9e48be7781b5d996874de2249c69992705a4..af3dadecb3ace02692546e5726fecd4e18ead8e7 100644
--- a/main.go
+++ b/main.go
@@ -4,6 +4,7 @@ import (
 	"dawn-weather/config"
 	"dawn-weather/errors"
 	"dawn-weather/persistence"
+	"fmt"
 
 	"github.com/ansrivas/fiberprometheus/v2"
 	swagger "github.com/arsmn/fiber-swagger/v2"
@@ -67,8 +68,11 @@ func createFiberConfig() fiber.Config {
 			if e, ok := err.(*errors.DawnError); ok {
 				code = e.Code
 				message = err.(*errors.DawnError).BuildStandardError(ctx)
+				err.(*errors.DawnError).LogString(ctx)
+			} else {
+				fmt.Println(err)
 			}
-			message.LogJson()
+			// message.LogJson()
 
 			err = ctx.Status(code).JSON(message)
 
diff --git a/models/csv.go b/models/csv.go
index cb3dd7bdb19dbbf41430ca3150429b95bb2c2b15..a71ec0a0d8ba80bd83124adb02afe0d3ffe8a675 100644
--- a/models/csv.go
+++ b/models/csv.go
@@ -32,7 +32,7 @@ type CSVRequest struct {
 	Primary        bool    `json:"primary"`
 	ComparisonYear int     `json:"comparison_year"`
 	Product        string  `json:"product"`
-	Range          int     `json:"range"`
+	Range          float64 `json:"range"`
 	Temperature    int     `json:"temperature"`
 	Year           int     `json:"year"`
 	Latitude       float64 `json:"latitude"`
@@ -76,6 +76,7 @@ func (r CSVRequest) Build(c *fiber.Ctx) CSVRequest {
 
 	latitude, _ := strconv.ParseFloat(c.Query("latitude", "-1000.0"), 64)
 	longitude, _ := strconv.ParseFloat(c.Query("longitude", "-1000.0"), 64)
+	_range, _ := strconv.ParseFloat(c.Query("range", "-1000.0"), 64)
 
 	newRequest := CSVRequest{
 		Analog:        parseBool(c.Query("analog")),
@@ -93,7 +94,7 @@ func (r CSVRequest) Build(c *fiber.Ctx) CSVRequest {
 
 		ComparisonYear: atoi(c.Query("comparison_year", "0")),
 		Product:        c.Query("product", "NONE"),
-		Range:          atoi(c.Query("range", "0")),
+		Range:          _range,
 		Temperature:    atoi(c.Query("temperature", "0")),
 		Year:           atoi(c.Query("year", "0")),
 		Latitude:       latitude,
diff --git a/services/data_download_service.go b/services/data_download_service.go
index 723782382c341a647011cbf850053fc4517287bf..7b3544e4de944f854ef151d71d49f498be576ceb 100644
--- a/services/data_download_service.go
+++ b/services/data_download_service.go
@@ -3,6 +3,7 @@ package services
 import (
 	"dawn-weather/errors"
 	"dawn-weather/models"
+	"dawn-weather/models/enums"
 	"dawn-weather/persistence"
 	"dawn-weather/persistence/entities"
 	"encoding/csv"
@@ -12,47 +13,56 @@ import (
 	"math"
 	"os"
 	"strconv"
+	"strings"
 	"time"
 
 	"github.com/google/uuid"
 )
 
+type CSVData struct {
+	Date          []time.Time
+	Analog        []float64
+	Cfs           []float64
+	CfsLower      []float64
+	CfsUpper      []float64
+	Comparison    []float64
+	FirstFreezing []int
+	LastFreezing  []int
+	GEFS          []float64
+	Maximum       []float64
+	Minimum       []float64
+	Normals       []float64
+	Primary       []float64
+}
+
 func fillKeys(request models.CSVRequest) []string {
 	keys := []string{}
 
-	if request.Analog {
-		keys = append(keys, "Date")
-	}
+	keys = append(keys, "Date")
 	if request.Analog {
 		keys = append(keys, "Analog Year GDD")
 	}
-	// if request.Cfs {
-	// 	keys = append(keys, "CFS GDD")
-	// }
-	// if request.CfsLower {
-	// 	keys = append(keys, "CFS Lower Boundary GDD")
-	// }
-	// if request.CfsUpper {
-	// 	keys = append(keys, "CFS Upper Boundary GDD")
-	// }
-	// if request.Comparison {
-	// 	keys = append(keys, "Comparison Year GDD")
-	// }
-	// if request.FirstFreezing {
-	// 	keys = append(keys, "First Freezing Date Counts")
-	// }
-	// if request.Gefs {
-	// 	keys = append(keys, "GEFS GDD")
-	// }
-	// if request.LastFreezing {
-	// 	keys = append(keys, "Last Freezing Date Counts")
-	// }
-	// if request.Maximum {
-	// 	keys = append(keys, "Confidence Interval Upper Boundary")
-	// }
-	// if request.Minimum {
-	// 	keys = append(keys, "Confidence Interval Lower Boundary")
-	// }
+	if request.Cfs || request.CfsLower || request.CfsUpper {
+		keys = append(keys, "CFS GDD")
+		keys = append(keys, "CFS Lower Boundary GDD")
+		keys = append(keys, "CFS Upper Boundary GDD")
+	}
+	if request.Comparison {
+		keys = append(keys, "Comparison Year GDD ("+strconv.Itoa(request.ComparisonYear)+")")
+	}
+	if request.FirstFreezing || request.LastFreezing {
+		keys = append(keys, "First Freezing Date Counts")
+		keys = append(keys, "Last Freezing Date Counts")
+	}
+	if request.Gefs {
+		keys = append(keys, "GEFS GDD")
+	}
+	if request.Maximum {
+		keys = append(keys, "Confidence Interval Upper Boundary")
+	}
+	if request.Minimum {
+		keys = append(keys, "Confidence Interval Lower Boundary")
+	}
 	if request.Normals {
 		keys = append(keys, "Thirty Year Normal GDD")
 	}
@@ -137,6 +147,282 @@ func getAnalogYear(request models.CSVRequest, dates []time.Time) []float64 {
 	return gddValues
 }
 
+func _parseDate(date string) time.Time {
+	const layout = "2006-Jan-02"
+	newDate, e := time.Parse(layout, date)
+	if e != nil {
+		panic(errors.DATE_PARSE_FAILURE.AddLogDetails(e.Error()))
+	}
+	return newDate
+}
+
+func parseDate(date string) time.Time {
+
+	split := strings.Split(date, "-")
+	day := split[1]
+	switch split[0] {
+	case "01":
+		return _parseDate("1981-Jan-" + day)
+	case "02":
+		return _parseDate("1981-Feb-" + day)
+	case "03":
+		return _parseDate("1981-Mar-" + day)
+	case "04":
+		return _parseDate("1981-Apr-" + day)
+	case "05":
+		return _parseDate("1981-May-" + day)
+	case "06":
+		return _parseDate("1981-Jun-" + day)
+	case "07":
+		return _parseDate("1981-Jul-" + day)
+	case "08":
+		return _parseDate("1981-Aug-" + day)
+	case "09":
+		return _parseDate("1981-Sep-" + day)
+	case "10":
+		return _parseDate("1981-Oct-" + day)
+	case "11":
+		return _parseDate("1981-Nov-" + day)
+	case "12":
+		return _parseDate("1981-Dev-" + day)
+	}
+	panic(errors.DATE_PARSE_FAILURE.AddLogDetails("Failed converting " + date + " to proper format."))
+}
+
+func getFreezingDates(request models.CSVRequest, dates []time.Time) [][]int {
+
+	freezingRequest := models.FreezingDateRequest{
+		Latitude:     request.Latitude,
+		Longitude:    request.Longitude,
+		FreezingTemp: request.Temperature,
+	}
+
+	response := GetFreezingDate(freezingRequest)
+
+	firstFreezingDates := make(map[time.Time]int)
+	lastFreezingDates := make(map[time.Time]int)
+	for k, v := range response.LastDateCounts {
+		date := parseDate(k)
+		lastFreezingDates[date] = v
+	}
+	for k, v := range response.FirstDateCounts {
+		date := parseDate(k)
+		firstFreezingDates[date] = v
+	}
+
+	date := time.Date(1981, time.January, 1, 0, 0, 0, 0, time.UTC)
+	lastFreezingValues := []int{}
+	firstFreezingValues := []int{}
+	for i := 0; i < 366; i++ {
+		if val, ok := lastFreezingDates[date]; ok {
+			lastFreezingValues = append(lastFreezingValues, val)
+			firstFreezingValues = append(firstFreezingValues, int(math.NaN()))
+		} else if val, ok := firstFreezingDates[date]; ok {
+			firstFreezingValues = append(firstFreezingValues, val)
+			lastFreezingValues = append(lastFreezingValues, int(math.NaN()))
+		} else {
+			firstFreezingValues = append(firstFreezingValues, int(math.NaN()))
+			lastFreezingValues = append(lastFreezingValues, int(math.NaN()))
+		}
+		date = date.Add(time.Duration(24) * time.Hour)
+	}
+	return [][]int{firstFreezingValues, lastFreezingValues}
+}
+
+func getComparisonYear(request models.CSVRequest, dates []time.Time) []float64 {
+	gddRequest := models.GddRequest{
+		Year:       request.ComparisonYear,
+		Product:    request.Product,
+		Latitude:   request.Latitude,
+		Longitude:  request.Longitude,
+		Accumulate: true,
+	}
+
+	gddValues := GetGddValues(gddRequest).GddValues
+	for len(gddValues) < 365 {
+		gddValues = append(gddValues, math.NaN())
+	}
+	return gddValues
+}
+
+func getConfidenceInterval(request models.CSVRequest, dates []time.Time) [][]float64 {
+
+	ciRequest := models.ConfidenceIntervalRequest{
+		Interval:  request.Range,
+		Product:   enums.GetProductFromString(request.Product),
+		Latitude:  request.Latitude,
+		Longitude: request.Longitude,
+	}
+
+	response := GetConfidenceInterval(ciRequest)
+
+	return [][]float64{response.LowerBound, response.UpperBound}
+}
+
+func getCfsData(request models.CSVRequest, dates []time.Time) [][]float64 {
+
+	gddRequest := models.GddRequest{
+		Year:       request.Year,
+		Product:    request.Product,
+		Latitude:   request.Latitude,
+		Longitude:  request.Longitude,
+		Accumulate: true,
+	}
+
+	response := GetCfsGddValues(gddRequest)
+	fullGddValues := []float64{}
+	fullLowerBound := []float64{}
+	fullUpperBound := []float64{}
+	in := false
+	after := false
+	c := 0
+	date := time.Date(response.FirstDate.Year(), time.January, 1, 0, 0, 0, 0, time.UTC)
+	for i := 0; i < 366; i++ {
+		if response.FirstDate.After(date) {
+			fullGddValues = append(fullGddValues, math.NaN())
+			fullLowerBound = append(fullLowerBound, math.NaN())
+			fullUpperBound = append(fullUpperBound, math.NaN())
+		} else {
+			if in || response.FirstDate == date {
+				if c >= len(response.GddValues) {
+					in = false
+					after = true
+				} else {
+					in = true
+					fullGddValues = append(fullGddValues, response.GddValues[c])
+					fullLowerBound = append(fullLowerBound, response.LowerBound[c])
+					fullUpperBound = append(fullUpperBound, response.UpperBound[c])
+					c += 1
+				}
+			} else if after {
+				fullGddValues = append(fullGddValues, math.NaN())
+				fullLowerBound = append(fullLowerBound, math.NaN())
+				fullUpperBound = append(fullUpperBound, math.NaN())
+			}
+		}
+		date = date.Add(time.Duration(24) * time.Hour)
+
+	}
+	return [][]float64{fullGddValues, fullLowerBound, fullUpperBound}
+}
+
+func getGefsData(request models.CSVRequest, dates []time.Time) []float64 {
+
+	gddRequest := models.GddRequest{
+		Year:       request.Year,
+		Product:    request.Product,
+		Latitude:   request.Latitude,
+		Longitude:  request.Longitude,
+		Accumulate: true,
+	}
+
+	response := GetGefsGddValues(gddRequest)
+	fullGddValues := []float64{}
+	in := false
+	after := false
+	c := 0
+	date := time.Date(response.FirstDate.Year(), time.January, 1, 0, 0, 0, 0, time.UTC)
+	for i := 0; i < 366; i++ {
+		if response.FirstDate.After(date) {
+			fullGddValues = append(fullGddValues, math.NaN())
+		} else {
+			if in || response.FirstDate == date {
+				if c >= len(response.GddValues) {
+					in = false
+					after = true
+				} else {
+					in = true
+					fullGddValues = append(fullGddValues, response.GddValues[c])
+					c += 1
+				}
+			} else if after {
+				fullGddValues = append(fullGddValues, math.NaN())
+			}
+		}
+		date = date.Add(time.Duration(24) * time.Hour)
+
+	}
+	return fullGddValues
+}
+
+func pullData(request models.CSVRequest) CSVData {
+	returnData := CSVData{}
+	dates := fillDates()
+	returnData.Date = dates
+
+	if request.Analog {
+		returnData.Analog = getAnalogYear(request, dates)
+	}
+	if request.Cfs || request.CfsLower || request.CfsUpper {
+		t := getCfsData(request, dates)
+		returnData.Cfs = t[0]
+		returnData.CfsLower = t[1]
+		returnData.CfsUpper = t[2]
+	}
+	if request.Comparison {
+		returnData.Comparison = getComparisonYear(request, dates)
+	}
+	if request.FirstFreezing || request.LastFreezing {
+		t := getFreezingDates(request, dates)
+		returnData.FirstFreezing = t[0]
+		returnData.LastFreezing = t[1]
+	}
+	if request.Gefs {
+		returnData.GEFS = getGefsData(request, dates)
+	}
+	if request.Maximum || request.Minimum {
+		ci := getConfidenceInterval(request, dates)
+		returnData.Maximum = ci[1]
+		returnData.Minimum = ci[0]
+	}
+	if request.Normals {
+		returnData.Normals = getNormals(request, dates)
+	}
+	if request.Primary {
+		returnData.Primary = getPrimary(request, dates)
+	}
+
+	return returnData
+}
+
+func createRecords(keys []string, data CSVData) [][]string {
+	records := [][]string{keys}
+	for i := 1; i < 366; i++ {
+		temp := []string{timeToString(data.Date[i-1])}
+		if len(data.Analog) != 0 {
+			temp = append(temp, fmt.Sprintf("%f", data.Analog[i-1]))
+		}
+		if len(data.Cfs) != 0 {
+			temp = append(temp, fmt.Sprintf("%f", data.Cfs[i-1]))
+			temp = append(temp, fmt.Sprintf("%f", data.CfsLower[i-1]))
+			temp = append(temp, fmt.Sprintf("%f", data.CfsUpper[i-1]))
+		}
+		if len(data.Comparison) != 0 {
+			temp = append(temp, fmt.Sprintf("%f", data.Comparison[i-1]))
+		}
+		if len(data.FirstFreezing) != 0 {
+			temp = append(temp, fmt.Sprintf("%d", data.FirstFreezing[i-1]))
+			temp = append(temp, fmt.Sprintf("%d", data.LastFreezing[i-1]))
+		}
+		if len(data.GEFS) != 0 {
+			temp = append(temp, fmt.Sprintf("%f", data.GEFS[i-1]))
+		}
+		if len(data.Maximum) != 0 {
+			temp = append(temp, fmt.Sprintf("%f", data.Maximum[i-1]))
+			temp = append(temp, fmt.Sprintf("%f", data.Minimum[i-1]))
+		}
+		if len(data.Normals) != 0 {
+			temp = append(temp, fmt.Sprintf("%f", data.Normals[i-1]))
+		}
+		if len(data.Primary) != 0 {
+			temp = append(temp, fmt.Sprintf("%f", data.Primary[i-1]))
+		}
+
+		records = append(records, temp)
+	}
+	return records
+}
+
 func GetDataDownload(request models.CSVRequest) string {
 
 	fileId := uuid.New()
@@ -150,21 +436,10 @@ func GetDataDownload(request models.CSVRequest) string {
 	w := csv.NewWriter(f)
 
 	keys := fillKeys(request)
-	dates := fillDates()
-	primary := getPrimary(request, dates)
-	normals := getNormals(request, dates)
-	analog := getAnalogYear(request, dates)
 
-	records := [][]string{keys}
+	data := pullData(request)
 
-	for i := 1; i < 366; i++ {
-		records = append(records,
-			[]string{timeToString(dates[i-1]),
-				fmt.Sprintf("%f", analog[i-1]),
-				fmt.Sprintf("%f", primary[i-1]),
-				fmt.Sprintf("%f", normals[i-1]),
-			})
-	}
+	records := createRecords(keys, data)
 
 	for _, record := range records {
 		if err := w.Write(record); err != nil {
@@ -176,6 +451,9 @@ func GetDataDownload(request models.CSVRequest) string {
 
 	fileText, err := ioutil.ReadFile(fileId.String() + ".csv")
 	f.Close()
-	os.Remove(fileId.String() + ".csv")
+	e := os.Remove(fileId.String() + ".csv")
+	if e != nil {
+		log.Fatal(e)
+	}
 	return string(fileText)
 }
diff --git a/services/freezing_date_service.go b/services/freezing_date_service.go
index 72add6366de082a08e676b44664f5ca655f099d0..5bb6c546c38f11186229863e1e0047c9feeded0e 100644
--- a/services/freezing_date_service.go
+++ b/services/freezing_date_service.go
@@ -31,7 +31,6 @@ func isLeapYear(year int) bool {
 
 func GetFreezingDate(request models.FreezingDateRequest) models.FreezingDateResponse {
 
-	// product := enums.GetProductFromString(request.Product)
 	var freezingDates entities.FreezingDates
 	freezingDates = persistence.FindFreezingDates(request.BuildLocation())