This repository has been archived on 2025-03-30. You can view files and clone it, but cannot push or open issues or pull requests.
bactdb/api/compare.go
2015-11-17 13:26:33 -07:00

142 lines
3.9 KiB
Go

package api
import (
"bytes"
"encoding/csv"
"encoding/json"
"fmt"
"net/http"
"strconv"
"strings"
"time"
"github.com/thermokarst/bactdb/Godeps/_workspace/src/github.com/gorilla/mux"
"github.com/thermokarst/bactdb/helpers"
"github.com/thermokarst/bactdb/payloads"
"github.com/thermokarst/bactdb/types"
)
// HandleCompare is a HTTP handler for comparision.
// Comparision requires a list of strain ids and a list of characteristic ids.
// The id order dictates the presentation order.
func HandleCompare(w http.ResponseWriter, r *http.Request) *types.AppError {
// types
type Comparisions map[string]map[string]string
type ComparisionsJSON [][]string
// vars
mimeType := r.FormValue("mimeType")
if mimeType == "" {
mimeType = "json"
}
claims := helpers.GetClaims(r)
var header string
var data []byte
// Get measurements for comparision
measService := MeasurementService{}
opt := r.URL.Query()
opt.Del("mimeType")
opt.Del("token")
opt.Add("Genus", mux.Vars(r)["genus"])
measurementsEntity, appErr := measService.List(&opt, &claims)
if appErr != nil {
return appErr
}
measurementsPayload := (measurementsEntity).(*payloads.Measurements)
// Assemble matrix
characteristicIDs := strings.Split(opt.Get("characteristic_ids"), ",")
strainIDs := strings.Split(opt.Get("strain_ids"), ",")
comparisions := make(Comparisions)
for _, characteristicID := range characteristicIDs {
characteristicIDInt, _ := strconv.ParseInt(characteristicID, 10, 0)
values := make(map[string]string)
for _, strainID := range strainIDs {
strainIDInt, _ := strconv.ParseInt(strainID, 10, 0)
for _, m := range *measurementsPayload.Measurements {
if (m.CharacteristicID == characteristicIDInt) && (m.StrainID == strainIDInt) {
if m.Notes.Valid {
values[strainID] = fmt.Sprintf("%s (%s)", m.Value(), m.Notes.String)
} else {
if values[strainID] != "" {
values[strainID] = fmt.Sprintf("%s; %s", values[strainID], m.Value())
} else {
values[strainID] = m.Value()
}
}
}
}
// If the strain doesn't have a measurement for this characteristic,
// stick an empty value in anyway (for CSV).
if _, ok := values[strainID]; !ok {
values[strainID] = ""
}
}
comparisions[characteristicID] = values
}
// Return, based on mimetype
switch mimeType {
case "json":
header = "application/json"
comparisionsJSON := make(ComparisionsJSON, 0)
for _, characteristicID := range characteristicIDs {
row := []string{characteristicID}
for _, strainID := range strainIDs {
row = append(row, comparisions[characteristicID][strainID])
}
comparisionsJSON = append(comparisionsJSON, row)
}
data, _ = json.Marshal(comparisionsJSON)
case "csv":
header = "text/csv"
// maps to translate ids
strains := make(map[string]string)
for _, strain := range *measurementsPayload.Strains {
var t string
if strain.TypeStrain {
t = "T"
}
strains[fmt.Sprintf("%d", strain.ID)] = fmt.Sprintf("%s %s %s", strain.SpeciesName(), strain.StrainName, t)
}
characteristics := make(map[string]string)
for _, characteristic := range *measurementsPayload.Characteristics {
characteristics[fmt.Sprintf("%d", characteristic.ID)] = characteristic.CharacteristicName
}
b := &bytes.Buffer{}
wr := csv.NewWriter(b)
// Write header row
r := []string{"Characteristic"}
for _, strainID := range strainIDs {
r = append(r, strains[strainID])
}
wr.Write(r)
// Write data
for _, characteristicID := range characteristicIDs {
r := []string{characteristics[characteristicID]}
for _, strainID := range strainIDs {
r = append(r, comparisions[characteristicID][strainID])
}
wr.Write(r)
}
wr.Flush()
data = b.Bytes()
w.Header().Set("Content-Disposition", fmt.Sprintf(`inline; filename="compare-%d.csv"`, int32(time.Now().Unix())))
}
// Wrap it up
w.Header().Set("Content-Type", header)
w.Write(data)
return nil
}