<commit_before>from sklearn import cross_validation
from readfacedatabases import *
import copy

# TODO: move to common?
def splitTrainTest(data1, data2, labels1, labels2, ratio):
  assert len(data1) == len(data2)
  assert len(labels1) == len(labels2)
  assert len(labels1) == len(data1)
  assert len(labels1) == len(labels2)

  data1, data2, labels1, labels2 = shuffle(data1, data2, labels1, labels2)

  # Random data for training and testing
  kf = cross_validation.KFold(n=len(data1), n_folds=ratio)
  for train, test in kf:
    break

  return (data1[train], data1[test], data2[train], data2[test],
          labels1[train], labels1[test], labels2[train], labels2[test])

def splitShuffling(shuffling, labelsShuffling):

  shuffling, labelsShuffling = shuffle(shuffling, labelsShuffling)

  labels = np.unique(labelsShuffling)

  # TODO: we already had this? maybe not remake it
  labelsToData = {}
  for label in labels:
    labelsToData[label] = list(shuffling[labels == label])
    print len(labelsToData[label])

  shuffledData1 = []
  shuffledData2 = []
  labelsData1 = []
  labelsData2 = []

  currentLabels = list(labelsShuffling)

  while len(shuffledData1) + len(shuffledData2) <= len(shuffling):
    print "len(shuffledData1) + len(shuffledData2)"
    print len(shuffledData1) + len(shuffledData2)
    print "len(shuffling)"
    print len(shuffling)

    label1 = np.random.choice(currentLabels, 1, replace=False)
    label2 = np.random.choice(np.array(list(currentLabels).remove(label1)), 1, replace=False)

    print label1
    print label2

    if label1 == label2:
      print " in first if"
      continue

    print "labelsToData"
    print labelsToData

    dataLabel1 = labelsToData[label1]
    dataLabel2 = labelsToData[label2]
    if len(dataLabel1) == 0:
      print "in second if"
      currentLabels.remove(label1)
      continue
    if len(dataLabel2) == 0:
      print "in second if"
      currentLabels.remove(label2)
      continue

    # data1LabelIndex = np.random.choice(len(labelsToData[label1]))
    # data2LabelIndex = np.random.choice(len(labelsToData[label2]))
    shuffledData1 += [dataLabel1[0]]
    shuffledData2 += [dataLabel2[0]]
    labelsData1 += [label1]
    labelsData2 += [label2]

    del labelsToData[label1][0]
    del labelsToData[label2][0]

    print "labelsToData"
    print labelsToData

  shuffledData1 = np.vstack(shuffledData1)
  shuffledData2 = np.vstack(shuffledData2)

  labelsData1 = np.hstack(labelsData1)
  labelsData2 = np.hstack(labelsData2)

  # remaing = list(shuffling)
  # remaininLabels = list(labelsShuffling)

  # print "shuffling size"
  # print len(shuffling)

  # shuffledData1 = []
  # shuffledData2 = []
  # labelsData1 = []
  # labelsData2 = []

  # for label in labels:
  #   print "label"
  #   print label

  #   nrRemainingData = len(remaing)

  #   if nrRemainingData == 0:
  #     break

  #   labelIndices = np.array(remaininLabels) == label
  #   concreteIndices = np.arange(nrRemainingData)[labelIndices]

  #   # If nothing of this label is left, just continue
  #   if len(concreteIndices) == 0:
  #     continue

  #   otherIndices = np.arange(nrRemainingData)[np.invert(labelIndices)]

  #   if len(otherIndices) == 0:
  #     continue

  #   indicesToTake = min(len(concreteIndices), len(otherIndices))

  #   otherIndices = np.random.choice(otherIndices, indicesToTake, replace=False)

  #   # concreteData = np.array(remaing)[concreteIndices]

  #   shuffledData1 += [np.array(remaing)[concreteIndices]]
  #   labelsData1 += [np.array(remaininLabels)[concreteIndices]]

  #   shuffledData2 += [np.array(remaing)[otherIndices]]
  #   labelsData2 += [np.array(remaininLabels)[otherIndices]]

  #   indicesToRemove = np.hstack((otherIndices, concreteIndices))
  #   remaing = [v for i, v in enumerate(remaing) if i not in indicesToRemove]
  #   remaininLabels = [v for i, v in enumerate(remaininLabels) if i not in indicesToRemove]

  #   assert len(remaing) == len(remaininLabels)

  # shuffledData1 = np.vstack(shuffledData1)
  # shuffledData2 = np.vstack(shuffledData2)

  # labelsData1 = np.hstack(labelsData1)
  # labelsData2 = np.hstack(labelsData2)

  # print shuffledData1.shape
  # print shuffledData2.shape

  # assert len(shuffledData1) == len(shuffledData2)
  # assert len(labelsData1) == len(labelsData2)

  # assert len(shuffledData1) <= len(shuffling) / 2

  """  STOP NEW METHOD """
  # shuffledData1 = shuffling[0: len(shuffling) / 2]
  # shuffledData2 = shuffling[len(shuffling)/2 :]

  # labelsData1 = labelsShuffling[0: len(shuffling) /2]
  # labelsData2 = labelsShuffling[len(shuffling)/2:]

  # shuffledData1 = np.array(shuffledData1)
  # shuffledData1 = np.array(shuffledData2)
  # labelsData1 = np.array(labelsData1)
  # labelsData2 = np.array(labelsData2)

  return shuffledData1, shuffledData2, labelsData1, labelsData2

# TODO: I think this can be written easier with the code similar to the Emotions one
# you can create more tuples than just one per image
# you can put each image in 5 tuples and that will probably owrk better
# it might be useful to also give the same image twice
def splitDataMultiPIESubject(imgsPerLabel=None):
  subjectsToImgs = readMultiPIESubjects()

  data1, data2, subjects1, subjects2, shuffling, subjectsShuffling = splitDataInPairsWithLabels(subjectsToImgs, imgsPerLabel, None)

  trainData1, testData1, trainData2, testData2, trainSubjects1, testSubjects1,\
        trainSubjects2, testSubjects2 = splitTrainTest(data1, data2, subjects1, subjects2, 5)

  print "trainData1.shape"
  print trainData1.shape

  shuffledData1, shuffledData2, subjectsData1, subjectsData2 = splitShuffling(shuffling, subjectsShuffling)

  print len(shuffledData1)
  print len(shuffledData2)

  trainShuffedData1, testShuffedData1, trainShuffedData2, testShuffedData2,\
    trainShuffledSubjects1, testShuffledSubjects1, trainShuffledSubjects2, testShuffledSubjects2 =\
        splitTrainTest(shuffledData1, shuffledData2,
                      subjectsData1, subjectsData2, 5)

  trainData1 = np.vstack((trainData1, trainShuffedData1))

  print "trainData1.shape"
  print trainData1.shape

  trainData2 = np.vstack((trainData2, trainShuffedData2))

  testData1 = np.vstack((testData1, testShuffedData1))
  testData2 = np.vstack((testData2, testShuffedData2))

  trainSubjects1 = np.hstack((trainSubjects1, trainShuffledSubjects1))
  testSubjects1 = np.hstack((testSubjects1, testShuffledSubjects1))

  trainSubjects2 = np.hstack((trainSubjects2, trainShuffledSubjects2))
  testSubjects2 = np.hstack((testSubjects2, testShuffledSubjects2))

  assert len(subjects1) == len(subjects2)
  assert len(trainSubjects1) == len(trainSubjects1)
  assert len(testSubjects1) == len(testSubjects2)

  similaritiesTrain = similarityDifferentLabels(trainSubjects1, trainSubjects2)
  similaritiesTest = similarityDifferentLabels(testSubjects1, testSubjects2)

  print "trainSubjects1.shape"
  print trainSubjects1.shape

  print "similaritiesTrain.shape"
  print similaritiesTrain.shape
  # print similaritiesTrain

  assert len(trainData1) == len(trainData2)
  assert len(testData1) == len(testData2)

  trainData1, trainData2, similaritiesTrain = shuffle3(trainData1, trainData2, similaritiesTrain)
  testData1, testData2, similaritiesTest = shuffle3(testData1, testData2, similaritiesTest)

  return trainData1, trainData2, testData1, testData2, similaritiesTrain, similaritiesTest

def splitDataInPairsWithLabels(labelsToImages, imgsPerLabel, labelsToTake=None):
  data1 = []
  data2 = []

  shuffling = []
  labelsShuffling = []
  labels1 = []
  labels2 = []

  for label, images in labelsToImages.iteritems():
    if labelsToTake is not None and label not in labelsToTake:
      print "skipping subject"
      continue

    # The database might contain the labels in similar
    # poses, and illumination conditions, so shuffle before
    np.random.shuffle(images)

    if imgsPerLabel is not None:
      images = images[:imgsPerLabel]

    delta = len(images) / 4 + label % 2
    last2Index = 2 * delta
    data1 += images[0: delta]
    data2 += images[delta: last2Index]

    labels1 += [label] * delta
    labels2 += [label] * delta

    imagesForShuffling = images[last2Index : ]
    shuffling += imagesForShuffling
    labelsShuffling += [label] * len(imagesForShuffling)

  print "len(labelsShuffling)"
  print len(labelsShuffling)

  print "shuffling"
  print len(shuffling)

  assert len(shuffling) == len(labelsShuffling)
  shuffling, labelsShuffling = shuffleList(shuffling, labelsShuffling)

  print len(data1)
  print len(data2)
  assert len(data1) == len(data2)

  data1 = np.array(data1)
  data2 = np.array(data2)
  labels1 = np.array(labels1)
  labels2 = np.array(labels2)
  shuffling = np.array(shuffling)
  labelsShuffling = np.array(labelsShuffling)

  return data1, data2, labels1, labels2, shuffling, labelsShuffling

def splitDataAccordingToLabels(labelsToImages, labelsToTake, imgsPerLabel=None):
  data1, data2, labels1, labels2, shuffling, labelsShuffling  = splitDataInPairsWithLabels(labelsToImages, imgsPerLabel, labelsToTake=labelsToTake)

  shuffledData1, shuffledData2, labelsData1, labelsData2 = splitShuffling(shuffling, labelsShuffling)

  data1 = np.vstack((data1, shuffledData1))
  data2 = np.vstack((data2, shuffledData2))

  labels1 = np.hstack((labels1, labelsData1))
  labels2 = np.hstack((labels2, labelsData2))

  return data1, data2, labels1, labels2

def similarityDifferentLabels(labels1, labels2):
  assert len(labels1) == len(labels2)
  return labels1 == labels2

def splitSimilarityYale():
  subjectsToImgs = readCroppedYaleSubjects()

  # Get all subjects
  data1, data2, subjects1, subjects2 = splitDataAccordingToLabels(subjectsToImgs,
                                          None, imgsPerLabel=None)

  return data1, data2, similarityDifferentLabels(subjects1, subjects2)

def splitSimilaritiesPIEEmotions():
  emotionToImages = readMultiPIEEmotions()
  # Get all emotions
  data1, data2, emotions1, emotions2 = splitDataAccordingToLabels(emotionToImages,
                                          None, imgsPerLabel=None)
  labels = similarityDifferentLabels(emotions1, emotions2)

  data1, data2, labels = shuffle3(data1, data2, labels)

  kf = cross_validation.KFold(n=len(data1), n_folds=5)
  for train, test in kf:
    break

  return (data1[train], data2[train], labels[train],
          data1[test], data2[test], labels[test])

def splitEmotionsMultiPieKeepSubjects():
  subjectToEmotions = readMultiPIEEmotionsPerSubject()

  totalData1 = []
  totalData2 = []
  totalLabels1 = []
  totalLabels2 = []
  for subject, emotionToImages in subjectToEmotions.iteritems():
    data1, data2, labels1, labels2 = splitDataAccordingToLabels(emotionToImages, None, None)
    totalData1 += [data1]
    totalData2 += [data2]
    totalLabels1 += [labels1]
    totalLabels2 += [labels2]

  totalData1 = np.vstack(totalData1)
  totalData1 = np.vstack(totalData2)
  totalLabels1 = np.hstack(totalLabels1)
  totalLabels2 = np.hstack(totalLabels2)
  return totalData1, totalData2, totalLabels1, totalLabels2

def splitEmotionsMultiPieKeepSubjectsTestTrain():
  kf = cross_validation.KFold(n=len(totalData1), n_folds=5)
  for train, test in kf:
    break

  labels = similarityDifferentLabels(totalLabels1, totalLabels2)

  return (totalData1[train], totalData2[train], labels[train],
          totalData1[test], totalData2[test], labels[test])

def testShuffling():
  shuffling = [1,2,3, 4]
  labelsShuffling = [1,2,3, 4]
  a, b, c, d  = splitShuffling(shuffling, labelsShuffling)
  assert not c[0] ==  d[0]
  assert not c[1] ==  d[1]
  assert sorted(list(a) + list(b)) == [1,2,3,4]

  shuffling = [1,2,3]
  labelsShuffling = [1,2,3]
  a, b, c, d  = splitShuffling(shuffling, labelsShuffling)
  assert not c[0] ==  d[0]
  assert not a[0] == b[0]

  shuffling = [1,2,4,5]
  labelsShuffling = [1,2,1,2]
  a, b, c, d  = splitShuffling(shuffling, labelsShuffling)
  assert not c[0] ==  d[0]
  assert not c[1] == d[1]

  fst = sorted(list(a[0]))
  snd = sorted(list(b[0]))

  assert fst == [1,4] or fst == [2,5]
  assert snd == [2,5] or snd == [1,4]

  if fst == [1,4]:
    assert c[0] == 1
  else:
    assert c[0] == 2

  shuffling = [ np.array([1,1]), np.array([2,2]), np.array([4,4]), np.array([5,5]),
                np.array([6, 6]), np.array([7, 7]) ]
  labelsShuffling = [1, 2, 3, 2, 1, 3]
  a, b, c, d  = splitShuffling(shuffling, labelsShuffling)
  assert not c[0] ==  d[0]
  assert not c[1] == d[1]
  assert not c[2] == d[2]

  print zip(a, c)
  print zip(b, d)

if __name__ == '__main__':
  # print shuffleList([1,2], [3,4])
  print len(shuffle([1,2], [3,4]))
  testShuffling()
<commit_msg>sampling from prpoer array<commit_after>from sklearn import cross_validation
from readfacedatabases import *
import copy

# TODO: move to common?
def splitTrainTest(data1, data2, labels1, labels2, ratio):
  assert len(data1) == len(data2)
  assert len(labels1) == len(labels2)
  assert len(labels1) == len(data1)
  assert len(labels1) == len(labels2)

  data1, data2, labels1, labels2 = shuffle(data1, data2, labels1, labels2)

  # Random data for training and testing
  kf = cross_validation.KFold(n=len(data1), n_folds=ratio)
  for train, test in kf:
    break

  return (data1[train], data1[test], data2[train], data2[test],
          labels1[train], labels1[test], labels2[train], labels2[test])

def splitShuffling(shuffling, labelsShuffling):

  shuffling, labelsShuffling = shuffle(shuffling, labelsShuffling)

  labels = np.unique(labelsShuffling)

  # TODO: we already had this? maybe not remake it
  labelsToData = {}
  for label in labels:
    labelsToData[label] = list(shuffling[labels == label])
    print len(labelsToData[label])

  shuffledData1 = []
  shuffledData2 = []
  labelsData1 = []
  labelsData2 = []

  currentLabels = list(labels)

  while len(shuffledData1) + len(shuffledData2) <= len(shuffling):
    print "len(shuffledData1) + len(shuffledData2)"
    print len(shuffledData1) + len(shuffledData2)
    print "len(shuffling)"
    print len(shuffling)

    label1 = np.random.choice(currentLabels, 1, replace=False)
    label2 = np.random.choice(np.array(list(currentLabels).remove(label1)), 1, replace=False)

    print label1
    print label2

    if label1 == label2:
      print " in first if"
      continue

    print "labelsToData"
    print labelsToData

    dataLabel1 = labelsToData[label1]
    dataLabel2 = labelsToData[label2]
    if len(dataLabel1) == 0:
      print "in second if"
      currentLabels.remove(label1)
      continue
    if len(dataLabel2) == 0:
      print "in second if"
      currentLabels.remove(label2)
      continue

    # data1LabelIndex = np.random.choice(len(labelsToData[label1]))
    # data2LabelIndex = np.random.choice(len(labelsToData[label2]))
    shuffledData1 += [dataLabel1[0]]
    shuffledData2 += [dataLabel2[0]]
    labelsData1 += [label1]
    labelsData2 += [label2]

    del labelsToData[label1][0]
    del labelsToData[label2][0]

    print "labelsToData"
    print labelsToData

  shuffledData1 = np.vstack(shuffledData1)
  shuffledData2 = np.vstack(shuffledData2)

  labelsData1 = np.hstack(labelsData1)
  labelsData2 = np.hstack(labelsData2)

  # remaing = list(shuffling)
  # remaininLabels = list(labelsShuffling)

  # print "shuffling size"
  # print len(shuffling)

  # shuffledData1 = []
  # shuffledData2 = []
  # labelsData1 = []
  # labelsData2 = []

  # for label in labels:
  #   print "label"
  #   print label

  #   nrRemainingData = len(remaing)

  #   if nrRemainingData == 0:
  #     break

  #   labelIndices = np.array(remaininLabels) == label
  #   concreteIndices = np.arange(nrRemainingData)[labelIndices]

  #   # If nothing of this label is left, just continue
  #   if len(concreteIndices) == 0:
  #     continue

  #   otherIndices = np.arange(nrRemainingData)[np.invert(labelIndices)]

  #   if len(otherIndices) == 0:
  #     continue

  #   indicesToTake = min(len(concreteIndices), len(otherIndices))

  #   otherIndices = np.random.choice(otherIndices, indicesToTake, replace=False)

  #   # concreteData = np.array(remaing)[concreteIndices]

  #   shuffledData1 += [np.array(remaing)[concreteIndices]]
  #   labelsData1 += [np.array(remaininLabels)[concreteIndices]]

  #   shuffledData2 += [np.array(remaing)[otherIndices]]
  #   labelsData2 += [np.array(remaininLabels)[otherIndices]]

  #   indicesToRemove = np.hstack((otherIndices, concreteIndices))
  #   remaing = [v for i, v in enumerate(remaing) if i not in indicesToRemove]
  #   remaininLabels = [v for i, v in enumerate(remaininLabels) if i not in indicesToRemove]

  #   assert len(remaing) == len(remaininLabels)

  # shuffledData1 = np.vstack(shuffledData1)
  # shuffledData2 = np.vstack(shuffledData2)

  # labelsData1 = np.hstack(labelsData1)
  # labelsData2 = np.hstack(labelsData2)

  # print shuffledData1.shape
  # print shuffledData2.shape

  # assert len(shuffledData1) == len(shuffledData2)
  # assert len(labelsData1) == len(labelsData2)

  # assert len(shuffledData1) <= len(shuffling) / 2

  """  STOP NEW METHOD """
  # shuffledData1 = shuffling[0: len(shuffling) / 2]
  # shuffledData2 = shuffling[len(shuffling)/2 :]

  # labelsData1 = labelsShuffling[0: len(shuffling) /2]
  # labelsData2 = labelsShuffling[len(shuffling)/2:]

  # shuffledData1 = np.array(shuffledData1)
  # shuffledData1 = np.array(shuffledData2)
  # labelsData1 = np.array(labelsData1)
  # labelsData2 = np.array(labelsData2)

  return shuffledData1, shuffledData2, labelsData1, labelsData2

# TODO: I think this can be written easier with the code similar to the Emotions one
# you can create more tuples than just one per image
# you can put each image in 5 tuples and that will probably owrk better
# it might be useful to also give the same image twice
def splitDataMultiPIESubject(imgsPerLabel=None):
  subjectsToImgs = readMultiPIESubjects()

  data1, data2, subjects1, subjects2, shuffling, subjectsShuffling = splitDataInPairsWithLabels(subjectsToImgs, imgsPerLabel, None)

  trainData1, testData1, trainData2, testData2, trainSubjects1, testSubjects1,\
        trainSubjects2, testSubjects2 = splitTrainTest(data1, data2, subjects1, subjects2, 5)

  print "trainData1.shape"
  print trainData1.shape

  shuffledData1, shuffledData2, subjectsData1, subjectsData2 = splitShuffling(shuffling, subjectsShuffling)

  print len(shuffledData1)
  print len(shuffledData2)

  trainShuffedData1, testShuffedData1, trainShuffedData2, testShuffedData2,\
    trainShuffledSubjects1, testShuffledSubjects1, trainShuffledSubjects2, testShuffledSubjects2 =\
        splitTrainTest(shuffledData1, shuffledData2,
                      subjectsData1, subjectsData2, 5)

  trainData1 = np.vstack((trainData1, trainShuffedData1))

  print "trainData1.shape"
  print trainData1.shape

  trainData2 = np.vstack((trainData2, trainShuffedData2))

  testData1 = np.vstack((testData1, testShuffedData1))
  testData2 = np.vstack((testData2, testShuffedData2))

  trainSubjects1 = np.hstack((trainSubjects1, trainShuffledSubjects1))
  testSubjects1 = np.hstack((testSubjects1, testShuffledSubjects1))

  trainSubjects2 = np.hstack((trainSubjects2, trainShuffledSubjects2))
  testSubjects2 = np.hstack((testSubjects2, testShuffledSubjects2))

  assert len(subjects1) == len(subjects2)
  assert len(trainSubjects1) == len(trainSubjects1)
  assert len(testSubjects1) == len(testSubjects2)

  similaritiesTrain = similarityDifferentLabels(trainSubjects1, trainSubjects2)
  similaritiesTest = similarityDifferentLabels(testSubjects1, testSubjects2)

  print "trainSubjects1.shape"
  print trainSubjects1.shape

  print "similaritiesTrain.shape"
  print similaritiesTrain.shape
  # print similaritiesTrain

  assert len(trainData1) == len(trainData2)
  assert len(testData1) == len(testData2)

  trainData1, trainData2, similaritiesTrain = shuffle3(trainData1, trainData2, similaritiesTrain)
  testData1, testData2, similaritiesTest = shuffle3(testData1, testData2, similaritiesTest)

  return trainData1, trainData2, testData1, testData2, similaritiesTrain, similaritiesTest

def splitDataInPairsWithLabels(labelsToImages, imgsPerLabel, labelsToTake=None):
  data1 = []
  data2 = []

  shuffling = []
  labelsShuffling = []
  labels1 = []
  labels2 = []

  for label, images in labelsToImages.iteritems():
    if labelsToTake is not None and label not in labelsToTake:
      print "skipping subject"
      continue

    # The database might contain the labels in similar
    # poses, and illumination conditions, so shuffle before
    np.random.shuffle(images)

    if imgsPerLabel is not None:
      images = images[:imgsPerLabel]

    delta = len(images) / 4 + label % 2
    last2Index = 2 * delta
    data1 += images[0: delta]
    data2 += images[delta: last2Index]

    labels1 += [label] * delta
    labels2 += [label] * delta

    imagesForShuffling = images[last2Index : ]
    shuffling += imagesForShuffling
    labelsShuffling += [label] * len(imagesForShuffling)

  print "len(labelsShuffling)"
  print len(labelsShuffling)

  print "shuffling"
  print len(shuffling)

  assert len(shuffling) == len(labelsShuffling)
  shuffling, labelsShuffling = shuffleList(shuffling, labelsShuffling)

  print len(data1)
  print len(data2)
  assert len(data1) == len(data2)

  data1 = np.array(data1)
  data2 = np.array(data2)
  labels1 = np.array(labels1)
  labels2 = np.array(labels2)
  shuffling = np.array(shuffling)
  labelsShuffling = np.array(labelsShuffling)

  return data1, data2, labels1, labels2, shuffling, labelsShuffling

def splitDataAccordingToLabels(labelsToImages, labelsToTake, imgsPerLabel=None):
  data1, data2, labels1, labels2, shuffling, labelsShuffling  = splitDataInPairsWithLabels(labelsToImages, imgsPerLabel, labelsToTake=labelsToTake)

  shuffledData1, shuffledData2, labelsData1, labelsData2 = splitShuffling(shuffling, labelsShuffling)

  data1 = np.vstack((data1, shuffledData1))
  data2 = np.vstack((data2, shuffledData2))

  labels1 = np.hstack((labels1, labelsData1))
  labels2 = np.hstack((labels2, labelsData2))

  return data1, data2, labels1, labels2

def similarityDifferentLabels(labels1, labels2):
  assert len(labels1) == len(labels2)
  return labels1 == labels2

def splitSimilarityYale():
  subjectsToImgs = readCroppedYaleSubjects()

  # Get all subjects
  data1, data2, subjects1, subjects2 = splitDataAccordingToLabels(subjectsToImgs,
                                          None, imgsPerLabel=None)

  return data1, data2, similarityDifferentLabels(subjects1, subjects2)

def splitSimilaritiesPIEEmotions():
  emotionToImages = readMultiPIEEmotions()
  # Get all emotions
  data1, data2, emotions1, emotions2 = splitDataAccordingToLabels(emotionToImages,
                                          None, imgsPerLabel=None)
  labels = similarityDifferentLabels(emotions1, emotions2)

  data1, data2, labels = shuffle3(data1, data2, labels)

  kf = cross_validation.KFold(n=len(data1), n_folds=5)
  for train, test in kf:
    break

  return (data1[train], data2[train], labels[train],
          data1[test], data2[test], labels[test])

def splitEmotionsMultiPieKeepSubjects():
  subjectToEmotions = readMultiPIEEmotionsPerSubject()

  totalData1 = []
  totalData2 = []
  totalLabels1 = []
  totalLabels2 = []
  for subject, emotionToImages in subjectToEmotions.iteritems():
    data1, data2, labels1, labels2 = splitDataAccordingToLabels(emotionToImages, None, None)
    totalData1 += [data1]
    totalData2 += [data2]
    totalLabels1 += [labels1]
    totalLabels2 += [labels2]

  totalData1 = np.vstack(totalData1)
  totalData1 = np.vstack(totalData2)
  totalLabels1 = np.hstack(totalLabels1)
  totalLabels2 = np.hstack(totalLabels2)
  return totalData1, totalData2, totalLabels1, totalLabels2

def splitEmotionsMultiPieKeepSubjectsTestTrain():
  kf = cross_validation.KFold(n=len(totalData1), n_folds=5)
  for train, test in kf:
    break

  labels = similarityDifferentLabels(totalLabels1, totalLabels2)

  return (totalData1[train], totalData2[train], labels[train],
          totalData1[test], totalData2[test], labels[test])

def testShuffling():
  shuffling = [1,2,3, 4]
  labelsShuffling = [1,2,3, 4]
  a, b, c, d  = splitShuffling(shuffling, labelsShuffling)
  assert not c[0] ==  d[0]
  assert not c[1] ==  d[1]
  assert sorted(list(a) + list(b)) == [1,2,3,4]

  shuffling = [1,2,3]
  labelsShuffling = [1,2,3]
  a, b, c, d  = splitShuffling(shuffling, labelsShuffling)
  assert not c[0] ==  d[0]
  assert not a[0] == b[0]

  shuffling = [1,2,4,5]
  labelsShuffling = [1,2,1,2]
  a, b, c, d  = splitShuffling(shuffling, labelsShuffling)
  assert not c[0] ==  d[0]
  assert not c[1] == d[1]

  fst = sorted(list(a[0]))
  snd = sorted(list(b[0]))

  assert fst == [1,4] or fst == [2,5]
  assert snd == [2,5] or snd == [1,4]

  if fst == [1,4]:
    assert c[0] == 1
  else:
    assert c[0] == 2

  shuffling = [ np.array([1,1]), np.array([2,2]), np.array([4,4]), np.array([5,5]),
                np.array([6, 6]), np.array([7, 7]) ]
  labelsShuffling = [1, 2, 3, 2, 1, 3]
  a, b, c, d  = splitShuffling(shuffling, labelsShuffling)
  assert not c[0] ==  d[0]
  assert not c[1] == d[1]
  assert not c[2] == d[2]

  print zip(a, c)
  print zip(b, d)

if __name__ == '__main__':
  # print shuffleList([1,2], [3,4])
  print len(shuffle([1,2], [3,4]))
  testShuffling()
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
import datetime
import time
import logging
import sqlalchemy as sa
from . import Base, engine, db
from .strategy import BUY, SELL, WAIT

log = logging.getLogger(__name__)

class Trade(Base):
    """Trading log"""
    __tablename__ = "trades"
    id = sa.Column(sa.Integer, primary_key=True)
    bot_id = sa.Column(sa.Integer, sa.ForeignKey('bots.id'))
    date = sa.Column(sa.DateTime, nullable=False, default=datetime.datetime.utcnow)
    order_type = sa.Column(sa.String, nullable=False)
    order_id = sa.Column(sa.Integer, nullable=False)
    trade_id = sa.Column(sa.Integer, nullable=False)
    market = sa.Column(sa.String, nullable=False)
    amount = sa.Column(sa.Float, nullable=False)
    rate = sa.Column(sa.Float, nullable=False)
    btc = sa.Column(sa.Float, nullable=False)
    btc_taxed = sa.Column(sa.Float, nullable=False)

    def __init__(self, bot_id, date, order_type, order_id, trade_id, market, amount, rate, btc, btc_taxed):
        """TODO: to be defined1.

        :bot_id: ID of the bot which initiated the trade
        :date: Date of the order
        :order_id: ID of the order
        :trade_id: ID of a single trade within the order
        :market: Currency_pair linke BTC_DASH
        :amount: How many coins bought/sold in order
        :rate: Rate for the order
        :order_type: Type of order. Can be either "BUY, SELL"
        :btc: How many BTC you placed in order
        :btc_taxed: How many BTC are actually used in order after applying the tax

        """
        self.bot_id = bot_id
        self.date = datetime.datetime.strptime(date, "%Y-%m-%d %H:%M:%S")
        self.order_type = order_type
        self.order_id = order_id
        self.trade_id = trade_id
        self.market = market
        self.amount = amount
        self.rate = rate
        self.btc = btc
        self.btc_taxed = btc_taxed
        log.info("{}: Bought {} for {}".format(self.date, self.amount, self.rate))

class Cointrader(Base):
    """Cointrader"""
    __tablename__ = "bots"
    id = sa.Column(sa.Integer, primary_key=True)
    created = sa.Column(sa.DateTime, nullable=False, default=datetime.datetime.utcnow)

    def __init__(self, market, strategy, resolution="30m", timeframe="1d"):
        self._market = market
        self._strategy = strategy
        self._resolution = resolution
        self._timeframe = timeframe

        self._amount = 0
        self._value = 0
        self._start_btc = 0
        self._btc = 0
        self._start_rate = 0

    def _buy(self):
        log.debug("Signal: BUY")
        self._amount, price = self._market.buy(self._btc)
        if self._start_rate == 0:
            self._start_rate = price
        self._btc = 0
        self._value = self._amount * price
        data = self._market.get_chart().data[-1]
        date = datetime.datetime.utcfromtimestamp(data["date"])
        log.info("{}: Bought {} for {}".format(date, self._amount, price))

    def _sell(self):
        log.debug("Signal: SELL")
        proceeds, price = self._market.sell(self._amount)
        self._value = 0
        self._btc = proceeds
        data = self._market.get_chart().data[-1]
        date = datetime.datetime.utcfromtimestamp(data["date"])
        log.info("{}: Sold {} for {} -> {}".format(date, self._amount, price, self._btc))
        self._amount = 0

    def stat(self):
        """Returns a dictionary with some statistic of the performance of the bot."""

        data = self._market.get_chart().data
        end_rate = data[-1]["close"]

        # Calculate the value in BTC at the end of the trade.
        if self._amount:
            end_btc = self._amount * end_rate
        else:
            end_btc = self._btc

        stat = {
            "start": datetime.datetime.utcfromtimestamp(data[0]["date"]),
            "end": datetime.datetime.utcfromtimestamp(data[-1]["date"]),
            "start_price": data[0]["close"],
            "end_price": data[-1]["close"],
            "start_btc": self._start_btc,
            "end_btc": end_btc,
            "profit_cointrader": ((end_btc - self._start_btc) / self._start_btc) * 100,
            "profit_chart": ((end_rate - self._start_rate) / self._start_rate) * 100
        }
        return stat

    def start(self, btc, interval=None, backtest=False):
        """Start the bot and begin trading with given amount of BTC.

        The bot will trigger a analysis of the chart every N seconds.
        The default number of seconds is set on initialisation using the
        `resolution` option. You can overwrite this setting
        by using the `interval` option.

        By setting the `backtest` option the trade will be simulated on
        real chart data. This is useful for testing to see how good
        your strategy performs.

        :btc: Amount of BTC to start trading with
        :interval: Number of seconds to wait until the bot again call
        for a trading signal. This defaults to the resolution of the bot
            which is provided on initialisation.
        :backtest: Simulate trading on historic chart data on the given market.
        :returns: None

        """
        self._start_btc = btc
        self._btc = btc
        if interval is None:
            interval = self._market._exchange.resolution2seconds(self._resolution)
        while 1:
            signal = self._strategy.signal(self._market, self._resolution, self._timeframe)
            if signal == BUY and self._btc > 0:
                self._buy()
            elif signal == SELL and self._amount:
                self._sell()
            elif signal == WAIT:
                log.debug("Signal: WAIT")
            if backtest:
                if not self._market.continue_backtest():
                    log.info("Backtest finished")
                    return self.stat()
            log.debug("ZZZ for {} seconds".format(interval))
            time.sleep(interval)
<commit_msg>Modified get_bot method to create/load a bot.<commit_after># -*- coding: utf-8 -*-
import datetime
import time
import logging
import sqlalchemy as sa
from . import Base, engine, db
from .strategy import BUY, SELL

log = logging.getLogger(__name__)

def init_db():
    Base.metadata.create_all(engine)

def get_bot(market, strategy, resolution, timeframe, btc):
    try:
        bot = db.query(Cointrader).filter(Cointrader.market == market._name).one()
        bot._market = market
        bot.strategy = str(strategy)
        bot._strategy = strategy
        bot._resolution = resolution
        bot._timeframe = timeframe
    except sa.orm.exc.NoResultFound:
        bot = Cointrader(market, strategy, resolution, timeframe)
        if btc is None:
            balances = market._exchange.get_balance()
            btc = balances["BTC"]["quantity"]
        bot.set_btc(btc)
        db.add(bot)
    db.commit()
    return bot

class Trade(Base):
    """Trading log"""
    __tablename__ = "trades"
    id = sa.Column(sa.Integer, primary_key=True)
    bot_id = sa.Column(sa.Integer, sa.ForeignKey('bots.id'))
    date = sa.Column(sa.DateTime, nullable=False, default=datetime.datetime.utcnow)
    order_type = sa.Column(sa.String, nullable=False)
    order_id = sa.Column(sa.Integer, nullable=False)
    trade_id = sa.Column(sa.Integer, nullable=False)
    market = sa.Column(sa.String, nullable=False)
    amount = sa.Column(sa.Float, nullable=False)
    rate = sa.Column(sa.Float, nullable=False)
    btc = sa.Column(sa.Float, nullable=False)
    btc_taxed = sa.Column(sa.Float, nullable=False)

    def __init__(self, bot_id, date, order_type, order_id, trade_id, market, amount, rate, btc, btc_taxed):
        """TODO: to be defined1.

        :bot_id: ID of the bot which initiated the trade
        :date: Date of the order
        :order_id: ID of the order
        :trade_id: ID of a single trade within the order
        :market: Currency_pair linke BTC_DASH
        :amount: How many coins bought/sold in order
        :rate: Rate for the order
        :order_type: Type of order. Can be either "BUY, SELL"
        :btc: How many BTC you placed in order
        :btc_taxed: How many BTC are actually used in order after applying the tax

        """
        self.bot_id = bot_id
        self.date = datetime.datetime.strptime(date, "%Y-%m-%d %H:%M:%S")
        self.order_type = order_type
        self.order_id = order_id
        self.trade_id = trade_id
        self.market = market
        self.amount = amount
        self.rate = rate
        self.btc = btc
        self.btc_taxed = btc_taxed
        log.info("{}: Bought {} for {}".format(self.date, self.amount, self.rate))

class Cointrader(Base):
    """Cointrader"""
    __tablename__ = "bots"
    id = sa.Column(sa.Integer, primary_key=True)
    created = sa.Column(sa.DateTime, nullable=False, default=datetime.datetime.utcnow)

    def __init__(self, market, strategy, resolution="30m", timeframe="1d"):
        self._market = market
        self._strategy = strategy
        self._resolution = resolution
        self._timeframe = timeframe

        self._amount = 0
        self._value = 0
        self._start_btc = 0
        self._btc = 0
        self._start_rate = 0

    def _buy(self):
        log.debug("Signal: BUY")
        self._amount, price = self._market.buy(self._btc)
        if self._start_rate == 0:
            self._start_rate = price
        self._btc = 0
        self._value = self._amount * price
        data = self._market.get_chart().data[-1]
        date = datetime.datetime.utcfromtimestamp(data["date"])
        log.info("{}: Bought {} for {}".format(date, self._amount, price))

    def _sell(self):
        log.debug("Signal: SELL")
        proceeds, price = self._market.sell(self._amount)
        self._value = 0
        self._btc = proceeds
        data = self._market.get_chart().data[-1]
        date = datetime.datetime.utcfromtimestamp(data["date"])
        log.info("{}: Sold {} for {} -> {}".format(date, self._amount, price, self._btc))
        self._amount = 0

    def stat(self):
        """Returns a dictionary with some statistic of the performance of the bot."""

        data = self._market.get_chart().data
        end_rate = data[-1]["close"]

        # Calculate the value in BTC at the end of the trade.
        if self._amount:
            end_btc = self._amount * end_rate
        else:
            end_btc = self._btc

        stat = {
            "start": datetime.datetime.utcfromtimestamp(data[0]["date"]),
            "end": datetime.datetime.utcfromtimestamp(data[-1]["date"]),
            "start_price": data[0]["close"],
            "end_price": data[-1]["close"],
            "start_btc": self._start_btc,
            "end_btc": end_btc,
            "profit_cointrader": ((end_btc - self._start_btc) / self._start_btc) * 100,
            "profit_chart": ((end_rate - self._start_rate) / self._start_rate) * 100
        }
        return stat

    def start(self, btc, interval=None, backtest=False):
        """Start the bot and begin trading with given amount of BTC.

        The bot will trigger a analysis of the chart every N seconds.
        The default number of seconds is set on initialisation using the
        `resolution` option. You can overwrite this setting
        by using the `interval` option.

        By setting the `backtest` option the trade will be simulated on
        real chart data. This is useful for testing to see how good
        your strategy performs.

        :btc: Amount of BTC to start trading with
        :interval: Number of seconds to wait until the bot again call
        for a trading signal. This defaults to the resolution of the bot
            which is provided on initialisation.
        :backtest: Simulate trading on historic chart data on the given market.
        :returns: None

        """
        self._start_btc = btc
        self._btc = btc
        if interval is None:
            interval = self._market._exchange.resolution2seconds(self._resolution)
        while 1:
            signal = self._strategy.signal(self._market, self._resolution, self._timeframe)
            if signal == BUY and self._btc > 0:
                self._buy()
            elif signal == SELL and self._amount:
                self._sell()
            elif signal == WAIT:
                log.debug("Signal: WAIT")
            if backtest:
                if not self._market.continue_backtest():
                    log.info("Backtest finished")
                    return self.stat()
            log.debug("ZZZ for {} seconds".format(interval))
            time.sleep(interval)
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
A Color Utility Library
-----------------------
colorutils provides utilities for working with colors, which are abstractly modeled by the Color class. The Color class
currently uses an internal RGB representation, but has allowances for RGB, HEX, and WEB formats.
"""
from __future__ import division
import random

from .static import *
from .equality import RGB_eq
from .convert import *

class Format:
    """
    Format contains well-known color formats which are supported by the Color class. This class is effectively
    an implementation of Enum for Python 2.7
    """
    RGB, HEX, WEB, YIQ, HSV = range(5)

class ArithmeticModel:
    """
    ArithmeticModel contains well-known arithmetic models which determine the additive behavior of the Color class. The
    default model is the light model (behaves similar to adding light). The alternative is the blend model, which
    averages the colors. This class is effectively an implementation of Enum for Python 2.7

    Note that Color subtraction happens in the same manner, regardless of the arithmetic model chosen.

    Reference: http://stackoverflow.com/questions/726549/algorithm-for-additive-color-mixing-for-rgb-values
    """
    LIGHT, BLEND = range(2)

class Color(object):
    """
    Color is the model which maintains the information for a color. If no color is specified on class instantiation,
    the color will default to black.

    The color formats which the Color class supports are enumerated in the Format class.

    Color equality defaults to RGB equality testing (where the r, g, and b values of one Color must equal the r, g,
    and b values of a second Color), however different equality functions can be used. Standard equality functions are
    provided by the colorutils package, or custom equality functions can be defined.

    The default additive model for Color instances behaves like the light model. Different additive models may be
    specified. The supported models are found in the ArithmeticModel class.
    """
    def __init__(self, color=None, **kwargs):
        """ Initialization """
        self.equality_fn = RGB_eq
        self.arithmetic = ArithmeticModel.LIGHT

        if isinstance(color, Color):
            self._color = color._color
        else:
            self._color = color if color else rgb_min

        for k, v in kwargs.items():
            setattr(self, k, v)

    def __eq__(self, other):
        """ Equals """
        if isinstance(other, Color):
            return self.equality_fn(self, other)
        return False

    def __ne__(self, other):
        """ Not Equals """
        return not self.__eq__(other)

    def __add__(self, other):
        """ Addition """
        if isinstance(other, Color):
            r1, g1, b1 = self.rgb
            r2, g2, b2 = other.rgb
        elif isinstance(other, tuple) and len(other) == 3:
            r1, g1, b1 = self.rgb
            r2, g2, b2 = other
        else:
            raise TypeError("Unsupported operand type(s) for +: '{0}' and '{1}'".format(type(self), type(other)))

        if self.arithmetic is ArithmeticModel.LIGHT:
            return Color((min(r1 + r2, rgb_max_val), min(g1 + g2, rgb_max_val), min(b1 + b2, rgb_max_val)))
        else:
            return Color(((r1 + r2 // 2), (g1 + g2 // 2), (b1 + b2 // 2)))

    def __sub__(self, other):
        """ Subtraction """
        if isinstance(other, Color):
            r1, g1, b1 = self.rgb
            r2, g2, b2 = other.rgb
        elif isinstance(other, tuple) and len(other) == 3:
            r1, g1, b1 = self.rgb
            r2, g2, b2 = other
        else:
            raise TypeError("Unsupported operand type(s) for -: '{0}' and '{1}'".format(type(self), type(other)))

        return Color((max(r1 - r2, rgb_min_val), max(g1 - g2, rgb_min_val), max(b1 - b2, rgb_min_val)))

    def __iter__(self):
        """ Iterator """
        return iter(self._color)

    def __str__(self):
        """ String representation """
        return "{}".format(self._color)

    def __repr__(self):
        """ General representation """
        return "<Color {}>".format(self._color)

    @property
    def red(self):
        """ The red component of the RGB color representation. """
        return self._color[0]

    @red.setter
    def red(self, value):
        self._color[0] = value

    @property
    def green(self):
        """ The green component of the RGB color representation. """
        return self._color[1]

    @green.setter
    def green(self, value):
        self._color[1] = value

    @property
    def blue(self):
        """ The blue component of the RGB color representation. """
        return self._color[2]

    @blue.setter
    def blue(self, value):
        self._color[2] = value

    @property
    def rgb(self):
        """ An RGB representation of the color. """
        return self._color

    @rgb.setter
    def rgb(self, value):
        self._color = value

    @property
    def hex(self):
        """ A 6-char HEX representation of the color, with a prepended octothorpe. """
        return rgb_to_hex(self.rgb)

    @hex.setter
    def hex(self, value):
        self._color = hex_to_rgb(value)

    @property
    def shorthex(self):
        """ The same as Color.hex, however, HEX values that can be minified to 3-char are returned as such. """
        return minify_hex(self.hex)

    @property
    def web(self):
        """ A WEB representation of the color. """
        return rgb_to_web(self.rgb)

    @web.setter
    def web(self, value):
        self._color = web_to_rgb(value)

    @property
    def yiq(self):
        """ A YIQ representation of the color. """
        return rgb_to_yiq(self.rgb)

    @yiq.setter
    def yiq(self, value):
        self._color = yiq_to_rgb(value)

    @property
    def hsv(self):
        """ An HSV representation of the color """
        return rgb_to_hsv(self.rgb)

    @hsv.setter
    def hsv(self, value):
        self._color = hsv_to_rgb(value)

# -----------------------------------------------
# Utility Functions
# -----------------------------------------------

# - - - - - - - - - - - - - - -
# Random Color Functions
# - - - - - - - - - - - - - - -

def random_rgb():
    """
    Generate a uniformly random RGB value.

    :return: A tuple of three integers with values between 0 and 255 inclusive
    """
    return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)

def random_hex():
    """
    Generate a uniformly random HEX value.

    :return: A string representing a random HEX value between 000000 and FFFFFF inclusive
    """
    return rgb_to_hex(random_rgb())

def random_web():
    """
    Generate a uniformly random WEB value.

    :return:
    """
    return rgb_to_web(random_rgb())

def offset_random_rgb(seed, amount=1):
    """
    Given a seed color, generate a specified number of random colors (1 color by default) determined by a randomized
    offset from the seed.

    :param seed:
    :param amount:
    :return:
    """
    r, g, b = seed

    results = []
    for _ in range(amount):
        base_val = ((r + g + b) / 3) + 1  # Add one to eliminate case where the base value would otherwise be 0
        new_val = base_val + (random.random() * rgb_max_val / 5)  # Randomly offset with an arbitrary multiplier
        ratio = new_val / base_val
        results.append((min(int(r*ratio), rgb_max_val), min(int(g*ratio), rgb_max_val), min(int(b*ratio), rgb_max_val)))

    return results[0] if len(results) > 1 else results

def offset_random_hex(seed, amount=1):
    """
    Given a seed color, generate a specified number of random colors (1 color by default) determined by a randomized
    offset from the seed.

    :param seed:
    :param amount:
    :return:
    """
    return rgb_to_hex(offset_random_rgb(seed, amount))

def offset_random_web(seed, amount=1):
    """
    Given a seed color, generate a specified number of random colors (1 color by default) determined by a randomized
    offset from the seed.

    :param seed:
    :param amount:
    :return:
    """
    return rgb_to_web(offset_random_rgb(seed, amount))

# - - - - - - - - - - - - - - -
# Other Color Functions
# - - - - - - - - - - - - - - -

def color_run(start_color, end_color, step_count, inclusive=True, to_color=True):
    """
    Given a start color, end color, and a number of steps, returns a list of colors which represent a 'scale' between
    the start and end color.

    :param start_color: The color starting the run
    :param end_color: The color ending the run
    :param step_count: The number of colors to have between the start and end color
    :param inclusive: Flag determining whether to include start and end values in run (default True)
    :param to_color: Flag indicating return values should be Color objects (default True)
    :return: List of colors between the start and end color
    :rtype: list
    """
    if isinstance(start_color, Color):
        start_color = start_color.rgb

    if isinstance(end_color, Color):
        end_color = end_color.rgb

    step = tuple((end_color[i] - start_color[i])/step_count for i in range(3))

    add = lambda x, y: tuple(sum(z) for z in zip(x, y))
    mult = lambda x, y: tuple(y * z for z in x)

    run = [add(start_color, mult(step, i)) for i in range(1, step_count)]

    if inclusive:
        run = [start_color] + run + [end_color]

    return run if not to_color else [Color(c) for c in run]

def text_color(background, dark_color=rgb_min, light_color=rgb_max):
    """
    Given a background color in the form of an RGB 3-tuple, returns the color the text should be (defaulting to white
    and black) for best readability. The light (white) and dark (black) defaults can be overridden to return preferred
    values.

    :param background:
    :param dark_color:
    :param light_color:
    :return:
    """
    max_y = rgb_to_yiq(rgb_max)[0]
    return light_color if rgb_to_yiq(background)[0] <= max_y / 2 else dark_color

def minify_hex(_hex):
    """
    Given a HEX value, tries to reduce it from a 6 character hex (e.g. #ffffff) to a 3 character hex (e.g. #fff).
    If the HEX value is unable to be minified, returns the 6 character HEX representation.

    :param _hex:
    :return:
    """
    size = len(_hex.strip('#'))
    if size == 3:
        return _hex
    elif size == 6:
        if _hex[1] == _hex[2] and _hex[3] == _hex[4] and _hex[5] == _hex[6]:
            return _hex[0::2]
        else:
            return _hex
    else:
        raise ColorException('Unexpected HEX size when minifying: {}'.format(size))
<commit_msg>Represent as a color swatch in rich-content capable python environments. (#13)<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
A Color Utility Library
-----------------------
colorutils provides utilities for working with colors, which are abstractly modeled by the Color class. The Color class
currently uses an internal RGB representation, but has allowances for RGB, HEX, and WEB formats.
"""
from __future__ import division
import random

from .static import *
from .equality import RGB_eq
from .convert import *

class Format:
    """
    Format contains well-known color formats which are supported by the Color class. This class is effectively
    an implementation of Enum for Python 2.7
    """
    RGB, HEX, WEB, YIQ, HSV = range(5)

class ArithmeticModel:
    """
    ArithmeticModel contains well-known arithmetic models which determine the additive behavior of the Color class. The
    default model is the light model (behaves similar to adding light). The alternative is the blend model, which
    averages the colors. This class is effectively an implementation of Enum for Python 2.7

    Note that Color subtraction happens in the same manner, regardless of the arithmetic model chosen.

    Reference: http://stackoverflow.com/questions/726549/algorithm-for-additive-color-mixing-for-rgb-values
    """
    LIGHT, BLEND = range(2)

class Color(object):
    """
    Color is the model which maintains the information for a color. If no color is specified on class instantiation,
    the color will default to black.

    The color formats which the Color class supports are enumerated in the Format class.

    Color equality defaults to RGB equality testing (where the r, g, and b values of one Color must equal the r, g,
    and b values of a second Color), however different equality functions can be used. Standard equality functions are
    provided by the colorutils package, or custom equality functions can be defined.

    The default additive model for Color instances behaves like the light model. Different additive models may be
    specified. The supported models are found in the ArithmeticModel class.
    """
    def __init__(self, color=None, **kwargs):
        """ Initialization """
        self.equality_fn = RGB_eq
        self.arithmetic = ArithmeticModel.LIGHT

        if isinstance(color, Color):
            self._color = color._color
        else:
            self._color = color if color else rgb_min

        for k, v in kwargs.items():
            setattr(self, k, v)

    def __eq__(self, other):
        """ Equals """
        if isinstance(other, Color):
            return self.equality_fn(self, other)
        return False

    def __ne__(self, other):
        """ Not Equals """
        return not self.__eq__(other)

    def __add__(self, other):
        """ Addition """
        if isinstance(other, Color):
            r1, g1, b1 = self.rgb
            r2, g2, b2 = other.rgb
        elif isinstance(other, tuple) and len(other) == 3:
            r1, g1, b1 = self.rgb
            r2, g2, b2 = other
        else:
            raise TypeError("Unsupported operand type(s) for +: '{0}' and '{1}'".format(type(self), type(other)))

        if self.arithmetic is ArithmeticModel.LIGHT:
            return Color((min(r1 + r2, rgb_max_val), min(g1 + g2, rgb_max_val), min(b1 + b2, rgb_max_val)))
        else:
            return Color(((r1 + r2 // 2), (g1 + g2 // 2), (b1 + b2 // 2)))

    def __sub__(self, other):
        """ Subtraction """
        if isinstance(other, Color):
            r1, g1, b1 = self.rgb
            r2, g2, b2 = other.rgb
        elif isinstance(other, tuple) and len(other) == 3:
            r1, g1, b1 = self.rgb
            r2, g2, b2 = other
        else:
            raise TypeError("Unsupported operand type(s) for -: '{0}' and '{1}'".format(type(self), type(other)))

        return Color((max(r1 - r2, rgb_min_val), max(g1 - g2, rgb_min_val), max(b1 - b2, rgb_min_val)))

    def __iter__(self):
        """ Iterator """
        return iter(self._color)

    def __str__(self):
        """ String representation """
        return "{}".format(self._color)

    def __repr__(self):
        """ General representation """
        return "<Color {}>".format(self._color)

    def _repr_html_(self):
        """ Rich representation for interactive notebook environments. """
        return '''

                rgb: {0}

                hex: {1}

                web: {2}

                yiq: {3}

                hsv: {4}

        '''.format(self.rgb, self.hex, self.web, self.yiq, self.hsv)

    @property
    def red(self):
        """ The red component of the RGB color representation. """
        return self._color[0]

    @red.setter
    def red(self, value):
        self._color[0] = value

    @property
    def green(self):
        """ The green component of the RGB color representation. """
        return self._color[1]

    @green.setter
    def green(self, value):
        self._color[1] = value

    @property
    def blue(self):
        """ The blue component of the RGB color representation. """
        return self._color[2]

    @blue.setter
    def blue(self, value):
        self._color[2] = value

    @property
    def rgb(self):
        """ An RGB representation of the color. """
        return self._color

    @rgb.setter
    def rgb(self, value):
        self._color = value

    @property
    def hex(self):
        """ A 6-char HEX representation of the color, with a prepended octothorpe. """
        return rgb_to_hex(self.rgb)

    @hex.setter
    def hex(self, value):
        self._color = hex_to_rgb(value)

    @property
    def shorthex(self):
        """ The same as Color.hex, however, HEX values that can be minified to 3-char are returned as such. """
        return minify_hex(self.hex)

    @property
    def web(self):
        """ A WEB representation of the color. """
        return rgb_to_web(self.rgb)

    @web.setter
    def web(self, value):
        self._color = web_to_rgb(value)

    @property
    def yiq(self):
        """ A YIQ representation of the color. """
        return rgb_to_yiq(self.rgb)

    @yiq.setter
    def yiq(self, value):
        self._color = yiq_to_rgb(value)

    @property
    def hsv(self):
        """ An HSV representation of the color """
        return rgb_to_hsv(self.rgb)

    @hsv.setter
    def hsv(self, value):
        self._color = hsv_to_rgb(value)

# -----------------------------------------------
# Utility Functions
# -----------------------------------------------

# - - - - - - - - - - - - - - -
# Random Color Functions
# - - - - - - - - - - - - - - -

def random_rgb():
    """
    Generate a uniformly random RGB value.

    :return: A tuple of three integers with values between 0 and 255 inclusive
    """
    return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)

def random_hex():
    """
    Generate a uniformly random HEX value.

    :return: A string representing a random HEX value between 000000 and FFFFFF inclusive
    """
    return rgb_to_hex(random_rgb())

def random_web():
    """
    Generate a uniformly random WEB value.

    :return:
    """
    return rgb_to_web(random_rgb())

def offset_random_rgb(seed, amount=1):
    """
    Given a seed color, generate a specified number of random colors (1 color by default) determined by a randomized
    offset from the seed.

    :param seed:
    :param amount:
    :return:
    """
    r, g, b = seed

    results = []
    for _ in range(amount):
        base_val = ((r + g + b) / 3) + 1  # Add one to eliminate case where the base value would otherwise be 0
        new_val = base_val + (random.random() * rgb_max_val / 5)  # Randomly offset with an arbitrary multiplier
        ratio = new_val / base_val
        results.append((min(int(r*ratio), rgb_max_val), min(int(g*ratio), rgb_max_val), min(int(b*ratio), rgb_max_val)))

    return results[0] if len(results) > 1 else results

def offset_random_hex(seed, amount=1):
    """
    Given a seed color, generate a specified number of random colors (1 color by default) determined by a randomized
    offset from the seed.

    :param seed:
    :param amount:
    :return:
    """
    return rgb_to_hex(offset_random_rgb(seed, amount))

def offset_random_web(seed, amount=1):
    """
    Given a seed color, generate a specified number of random colors (1 color by default) determined by a randomized
    offset from the seed.

    :param seed:
    :param amount:
    :return:
    """
    return rgb_to_web(offset_random_rgb(seed, amount))

# - - - - - - - - - - - - - - -
# Other Color Functions
# - - - - - - - - - - - - - - -

def color_run(start_color, end_color, step_count, inclusive=True, to_color=True):
    """
    Given a start color, end color, and a number of steps, returns a list of colors which represent a 'scale' between
    the start and end color.

    :param start_color: The color starting the run
    :param end_color: The color ending the run
    :param step_count: The number of colors to have between the start and end color
    :param inclusive: Flag determining whether to include start and end values in run (default True)
    :param to_color: Flag indicating return values should be Color objects (default True)
    :return: List of colors between the start and end color
    :rtype: list
    """
    if isinstance(start_color, Color):
        start_color = start_color.rgb

    if isinstance(end_color, Color):
        end_color = end_color.rgb

    step = tuple((end_color[i] - start_color[i])/step_count for i in range(3))

    add = lambda x, y: tuple(sum(z) for z in zip(x, y))
    mult = lambda x, y: tuple(y * z for z in x)

    run = [add(start_color, mult(step, i)) for i in range(1, step_count)]

    if inclusive:
        run = [start_color] + run + [end_color]

    return run if not to_color else [Color(c) for c in run]

def text_color(background, dark_color=rgb_min, light_color=rgb_max):
    """
    Given a background color in the form of an RGB 3-tuple, returns the color the text should be (defaulting to white
    and black) for best readability. The light (white) and dark (black) defaults can be overridden to return preferred
    values.

    :param background:
    :param dark_color:
    :param light_color:
    :return:
    """
    max_y = rgb_to_yiq(rgb_max)[0]
    return light_color if rgb_to_yiq(background)[0] <= max_y / 2 else dark_color

def minify_hex(_hex):
    """
    Given a HEX value, tries to reduce it from a 6 character hex (e.g. #ffffff) to a 3 character hex (e.g. #fff).
    If the HEX value is unable to be minified, returns the 6 character HEX representation.

    :param _hex:
    :return:
    """
    size = len(_hex.strip('#'))
    if size == 3:
        return _hex
    elif size == 6:
        if _hex[1] == _hex[2] and _hex[3] == _hex[4] and _hex[5] == _hex[6]:
            return _hex[0::2]
        else:
            return _hex
    else:
        raise ColorException('Unexpected HEX size when minifying: {}'.format(size))
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
CIE 1964 U*V*W* Colourspace
===========================

Defines the *CIE 1964 U\*V\*W\** colourspace transformations:

-   :func:`colour.XYZ_to_UVW`

See Also
--------
`CIE U*V*W* Colourspace Jupyter Notebook
<http://nbviewer.jupyter.org/github/colour-science/colour-notebooks/\
blob/master/notebooks/models/cie_uvw.ipynb>`_

References
----------
-   :cite:`Wikipediacj` : Wikipedia. (n.d.). CIE 1964 color space. Retrieved
    June 10, 2014, from http://en.wikipedia.org/wiki/CIE_1964_color_space
"""

from __future__ import division, unicode_literals

from colour.colorimetry import ILLUMINANTS
from colour.models import (UCS_to_uv, UCS_uv_to_xy, XYZ_to_UCS, XYZ_to_xyY,
                           xy_to_UCS_uv, xyY_to_XYZ, xyY_to_xy)
from colour.utilities import tsplit, tstack

__author__ = 'Colour Developers'
__copyright__ = 'Copyright (C) 2013-2018 - Colour Developers'
__license__ = 'New BSD License - http://opensource.org/licenses/BSD-3-Clause'
__maintainer__ = 'Colour Developers'
__email__ = 'colour-science@googlegroups.com'
__status__ = 'Production'

__all__ = ['XYZ_to_UVW', 'UVW_to_XYZ']

def XYZ_to_UVW(
        XYZ,
        illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D50']):
    """
    Converts from *CIE XYZ* tristimulus values to *CIE 1964 U\*V\*W\**
    colourspace.

    Parameters
    ----------
    XYZ : array_like
        *CIE XYZ* tristimulus values.
    illuminant : array_like, optional
        Reference *illuminant* *xy* chromaticity coordinates or *CIE xyY*
        colourspace array.

    Returns
    -------
    ndarray
        *CIE 1964 U\*V\*W\** colourspace array.

    Warning
    -------
    The input domain and output range of that definition are non standard!

    Notes
    -----
    -   Input *CIE XYZ* tristimulus values are normalised to domain [0, 100].
    -   Input *illuminant* *xy* chromaticity coordinates or *CIE xyY*
        colourspace array are normalised to domain [0, 1].
    -   Output *CIE 1964 U\*V\*W\** colourspace array is normalised to range
        [0, 100].

    References
    ----------
    -   :cite:`Wikipediacj`

    Examples
    --------
    >>> import numpy as np
    >>> XYZ = np.array([0.07049534, 0.10080000, 0.09558313]) * 100
    >>> XYZ_to_UVW(XYZ)  # doctest: +ELLIPSIS
    array([-28.0579733...,  -0.8819449...,  37.0041149...])
    """

    xyY = XYZ_to_xyY(XYZ, xyY_to_xy(illuminant))
    _x, _y, Y = tsplit(xyY)

    u, v = tsplit(UCS_to_uv(XYZ_to_UCS(XYZ)))
    u_0, v_0 = tsplit(xy_to_UCS_uv(xyY_to_xy(illuminant)))

    W = 25 * Y ** (1 / 3) - 17
    U = 13 * W * (u - u_0)
    V = 13 * W * (v - v_0)

    UVW = tstack((U, V, W))

    return UVW

def UVW_to_XYZ(
        UVW,
        illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D50']):
    """
    Converts *CIE 1964 U\*V\*W\** colourspace to *CIE XYZ* tristimulus values.

    Parameters
    ----------
    UVW : array_like
        *CIE 1964 U\*V\*W\** colourspace array.
    illuminant : array_like, optional
        Reference *illuminant* *xy* chromaticity coordinates or *CIE xyY*
        colourspace array.

    Returns
    -------
    ndarray
        *CIE XYZ* tristimulus values.

    Warning
    -------
    The input domain and output range of that definition are non standard!

    Notes
    -----
    -   Input *CIE 1964 U\*V\*W\** colourspace array is normalised to domain
        [0, 100].
    -   Output *CIE XYZ* tristimulus values are normalised to range [0, 100].
    -   Output *illuminant* *xy* chromaticity coordinates or *CIE xyY*
        colourspace array are normalised to range [0, 1].

    References
    ----------
    -   :cite:`Wikipediacj`

    Examples
    --------
    >>> import numpy as np
    >>> UVW = np.array([-28.05797333, -0.88194493, 37.00411491])
    >>> UVW_to_XYZ(UVW)  # doctest: +ELLIPSIS
    array([  7.049534...,  10.08    ...,   9.558313...])
    """

    U, V, W = tsplit(UVW)
    u_0, v_0 = tsplit(xy_to_UCS_uv(xyY_to_xy(illuminant)))

    Y = ((W + 17) / 25) ** 3
    u = U / (13 * W) + u_0
    v = V / (13 * W) + v_0

    x, y = tsplit(UCS_uv_to_xy(tstack((u, v))))

    XYZ = xyY_to_XYZ(tstack((x, y, Y)))

    return XYZ
<commit_msg>Update various docstrings.<commit_after># -*- coding: utf-8 -*-
"""
CIE 1964 U*V*W* Colourspace
===========================

Defines the *CIE 1964 U\*V\*W\** colourspace transformations:

-   :func:`colour.XYZ_to_UVW`
-   :func:`colour.UVW_to_XYZ`

See Also
--------
`CIE U*V*W* Colourspace Jupyter Notebook
<http://nbviewer.jupyter.org/github/colour-science/colour-notebooks/\
blob/master/notebooks/models/cie_uvw.ipynb>`_

References
----------
-   :cite:`Wikipediacj` : Wikipedia. (n.d.). CIE 1964 color space. Retrieved
    June 10, 2014, from http://en.wikipedia.org/wiki/CIE_1964_color_space
"""

from __future__ import division, unicode_literals

from colour.colorimetry import ILLUMINANTS
from colour.models import (UCS_to_uv, UCS_uv_to_xy, XYZ_to_UCS, XYZ_to_xyY,
                           xy_to_UCS_uv, xyY_to_XYZ, xyY_to_xy)
from colour.utilities import tsplit, tstack

__author__ = 'Colour Developers'
__copyright__ = 'Copyright (C) 2013-2018 - Colour Developers'
__license__ = 'New BSD License - http://opensource.org/licenses/BSD-3-Clause'
__maintainer__ = 'Colour Developers'
__email__ = 'colour-science@googlegroups.com'
__status__ = 'Production'

__all__ = ['XYZ_to_UVW', 'UVW_to_XYZ']

def XYZ_to_UVW(
        XYZ,
        illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D50']):
    """
    Converts from *CIE XYZ* tristimulus values to *CIE 1964 U\*V\*W\**
    colourspace.

    Parameters
    ----------
    XYZ : array_like
        *CIE XYZ* tristimulus values.
    illuminant : array_like, optional
        Reference *illuminant* *xy* chromaticity coordinates or *CIE xyY*
        colourspace array.

    Returns
    -------
    ndarray
        *CIE 1964 U\*V\*W\** colourspace array.

    Warning
    -------
    The input domain and output range of that definition are non standard!

    Notes
    -----
    -   Input *CIE XYZ* tristimulus values are normalised to domain [0, 100].
    -   Input *illuminant* *xy* chromaticity coordinates or *CIE xyY*
        colourspace array are normalised to domain [0, 1].
    -   Output *CIE 1964 U\*V\*W\** colourspace array is normalised to range
        [0, 100].

    References
    ----------
    -   :cite:`Wikipediacj`

    Examples
    --------
    >>> import numpy as np
    >>> XYZ = np.array([0.07049534, 0.10080000, 0.09558313]) * 100
    >>> XYZ_to_UVW(XYZ)  # doctest: +ELLIPSIS
    array([-28.0579733...,  -0.8819449...,  37.0041149...])
    """

    xyY = XYZ_to_xyY(XYZ, xyY_to_xy(illuminant))
    _x, _y, Y = tsplit(xyY)

    u, v = tsplit(UCS_to_uv(XYZ_to_UCS(XYZ)))
    u_0, v_0 = tsplit(xy_to_UCS_uv(xyY_to_xy(illuminant)))

    W = 25 * Y ** (1 / 3) - 17
    U = 13 * W * (u - u_0)
    V = 13 * W * (v - v_0)

    UVW = tstack((U, V, W))

    return UVW

def UVW_to_XYZ(
        UVW,
        illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D50']):
    """
    Converts *CIE 1964 U\*V\*W\** colourspace to *CIE XYZ* tristimulus values.

    Parameters
    ----------
    UVW : array_like
        *CIE 1964 U\*V\*W\** colourspace array.
    illuminant : array_like, optional
        Reference *illuminant* *xy* chromaticity coordinates or *CIE xyY*
        colourspace array.

    Returns
    -------
    ndarray
        *CIE XYZ* tristimulus values.

    Warning
    -------
    The input domain and output range of that definition are non standard!

    Notes
    -----
    -   Input *CIE 1964 U\*V\*W\** colourspace array is normalised to domain
        [0, 100].
    -   Output *CIE XYZ* tristimulus values are normalised to range [0, 100].
    -   Output *illuminant* *xy* chromaticity coordinates or *CIE xyY*
        colourspace array are normalised to range [0, 1].

    References
    ----------
    -   :cite:`Wikipediacj`

    Examples
    --------
    >>> import numpy as np
    >>> UVW = np.array([-28.05797333, -0.88194493, 37.00411491])
    >>> UVW_to_XYZ(UVW)  # doctest: +ELLIPSIS
    array([  7.049534...,  10.08    ...,   9.558313...])
    """

    U, V, W = tsplit(UVW)
    u_0, v_0 = tsplit(xy_to_UCS_uv(xyY_to_xy(illuminant)))

    Y = ((W + 17) / 25) ** 3
    u = U / (13 * W) + u_0
    v = V / (13 * W) + v_0

    x, y = tsplit(UCS_uv_to_xy(tstack((u, v))))

    XYZ = xyY_to_XYZ(tstack((x, y, Y)))

    return XYZ
<|endoftext|>


<commit_before>from django.conf.urls.defaults import *

from coltrane.models import Entry

entry_info_dict = {'queryset':Entry.live.all(), 'date_field': 'pub_date', }

urlpatterns = patterns('',
# Pagination for the equivalent of archive_index generic view.
# The url is of the form http://host/page/4/
# In urls.py for example, ('^blog/page/(?P<page>\d)/$', get_archive_index),
	(r'^$', 'coltrane.views.get_archive_index_first', ),
	(r'^page/(?P<page>\d)/$', 'coltrane.views.get_archive_index', ),
	#(r'^$', 'django.views.generic.date_based.archive_index', entry_info_dict,  'coltrane_entry_archive_index'),
	(r'^(?P<year>\d{4})/$', 'django.views.generic.date_based.archive_year', entry_info_dict, 'coltrane_entry_archive_year'),
	(r'^(?P<year>\d{4})/(?P<month>\w{3})/$', 'django.views.generic.date_based.archive_month', entry_info_dict, 'coltrane_entry_archive_month'),
	(r'^(?P<year>\d{4})/(?P<month>\w{3})/(?P<day>\d{2})/$', 'django.views.generic.date_based.archive_day', entry_info_dict, 'coltrane_entry_archive_day'),
	(r'^(?P<year>\d{4})/(?P<month>\w{3})/(?P<day>\d{2})/(?P<slug>[-\w]+)/$', 'django.views.generic.date_based.object_detail', entry_info_dict, 'coltrane_entry_detail'),
)<commit_msg>Migrated function-based generic views to class-based<commit_after>from django.conf.urls.defaults import *
from django.views.generic.dates import YearArchiveView, MonthArchiveView, DayArchiveView, DateDetailView

from coltrane.models import Entry

entry_info_dict = {'queryset':Entry.live.all(), 'date_field': 'pub_date', }

urlpatterns = patterns('',
# Pagination for the equivalent of archive_index generic view.
# The url is of the form http://host/page/4/
# In urls.py for example, ('^blog/page/(?P<page>\d)/$', get_archive_index),
	url(r'^$', 'coltrane.views.get_archive_index_first', ),
	url(r'^page/(?P<page>\d)/$', 'coltrane.views.get_archive_index', ),
	#(r'^$', 'django.views.generic.date_based.archive_index', entry_info_dict,  'coltrane_entry_archive_index'),
	#(r'^(?P<year>\d{4})/$', YearArchiveView.as_view(), entry_info_dict, 'coltrane_entry_archive_year'),
	url(r'^(?P<year>\d{4})/$', YearArchiveView.as_view(**entry_info_dict), name= 'coltrane_entry_archive_year'),
	url(r'^(?P<year>\d{4})/(?P<month>\w{3})/$', MonthArchiveView.as_view(**entry_info_dict), name= 'coltrane_entry_archive_month'),
	url(r'^(?P<year>\d{4})/(?P<month>\w{3})/(?P<day>\d{2})/$', DayArchiveView.as_view(**entry_info_dict), name= 'coltrane_entry_archive_day'),
	url(r'^(?P<year>\d{4})/(?P<month>\w{3})/(?P<day>\d{2})/(?P<slug>[-\w]+)/$', DateDetailView.as_view(**entry_info_dict), name= 'coltrane_entry_detail'),
)<|endoftext|>


<commit_before>from comics.aggregator.crawler import CrawlerBase, CrawlerImage
from comics.comics.rocky import ComicData as RockyData

class ComicData(RockyData):
    name = "Rocky (bt.no)"
    url = "https://www.bt.no/kultur/tegneserier/"

class Crawler(CrawlerBase):
    history_capable_date = "2008-07-01"
    schedule = "Mo,Tu,We,Th,Fr,Sa"
    time_zone = "Europe/Oslo"

    def crawl(self, pub_date):
        url = "https://cartoon-prod.schibsted.tech/rocky/%s.gif" % (
            pub_date.strftime("%d%m%y"),
        )
        return CrawlerImage(url)
<commit_msg>Rocky is no longer published on bt.no<commit_after>from comics.aggregator.crawler import CrawlerBase
from comics.comics.rocky import ComicData as RockyData

class ComicData(RockyData):
    name = "Rocky (bt.no)"
    url = "https://www.bt.no/kultur/tegneserier/"
    active = False

class Crawler(CrawlerBase):
    def crawl(self, pub_date):
        pass
<|endoftext|>


<commit_before>class git(Wig):
	tarball_uri = 'https://github.com/git/git/archive/v$RELEASE_VERSION$.tar.gz'
	last_release_version = 'v2.10.1'
	git_uri = 'https://github.com/git/git'
<commit_msg>Update git.py<commit_after>class git(Wig):
	tarball_uri = 'https://github.com/git/git/archive/v$RELEASE_VERSION$.tar.gz'
	last_release_version = 'v2.10.1'
	git_uri = 'https://github.com/git/git'

	def setup(self):
		self.before_configure += [S.make(['configure'])]
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from cms.forms.utils import get_site_choices, get_page_choices
from cms.models import Page, PageUser, Placeholder
from cms.plugin_pool import plugin_pool
from cms.utils import get_language_from_request, cms_static_url
from django.conf import settings
from django.contrib.sites.models import Site
from django.forms.widgets import Select, MultiWidget, Widget
from django.template.context import RequestContext
from django.template.loader import render_to_string
from django.utils.encoding import force_unicode
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext as _
import copy
from cms.templatetags.cms_admin import CMS_ADMIN_ICON_BASE

class PageSelectWidget(MultiWidget):
    """A widget that allows selecting a page by first selecting a site and then
    a page on that site in a two step process.
    """
    def __init__(self, site_choices=None, page_choices=None, attrs=None):
        if attrs is not None:
            self.attrs = attrs.copy()
        else:
            self.attrs = {}
        if site_choices is None or page_choices is None:
            site_choices, page_choices = get_site_choices(), get_page_choices()
        self.site_choices = site_choices
        self.choices = page_choices
        widgets = (Select(choices=site_choices ),
                   Select(choices=[('', '----')]),
                   Select(choices=self.choices, attrs={'style': "display:none;"} ),
        )
        super(PageSelectWidget, self).__init__(widgets, attrs)

    def decompress(self, value):
        """
        receives a page_id in value and returns the site_id and page_id
        of that page or the current site_id and None if no page_id is given.
        """
        if value:
            page = Page.objects.get(pk=value)
            site = page.site
            return [site.pk, page.pk, page.pk]
        site = Site.objects.get_current()
        return [site.pk,None,None]

    def _has_changed(self, initial, data):
        # THIS IS A COPY OF django.forms.widgets.Widget._has_changed()
        # (except for the first if statement)

        """
        Return True if data differs from initial.
        """
        # For purposes of seeing whether something has changed, None is
        # the same as an empty string, if the data or inital value we get
        # is None, replace it w/ u''.
        if data is None or (len(data)>=2 and data[1] in [None,'']):
            data_value = u''
        else:
            data_value = data
        if initial is None:
            initial_value = u''
        else:
            initial_value = initial
        if force_unicode(initial_value) != force_unicode(data_value):
            return True
        return False

    def render(self, name, value, attrs=None):
        # THIS IS A COPY OF django.forms.widgets.MultiWidget.render()
        # (except for the last line)

        # value is a list of values, each corresponding to a widget
        # in self.widgets.
        if not isinstance(value, list):
            value = self.decompress(value)
        output = []
        final_attrs = self.build_attrs(attrs)
        id_ = final_attrs.get('id', None)
        for i, widget in enumerate(self.widgets):
            try:
                widget_value = value[i]
            except IndexError:
                widget_value = None
            if id_:
                final_attrs = dict(final_attrs, id='%s_%s' % (id_, i))
            output.append(widget.render(name + '_%s' % i, widget_value, final_attrs))
        output.append(r'''''' % {'name': name})
        return mark_safe(self.format_output(output))

    def format_output(self, rendered_widgets):
        return u' '.join(rendered_widgets)

class PluginEditor(Widget):
    def __init__(self, attrs=None):
        if attrs is not None:
            self.attrs = attrs.copy()
        else:
            self.attrs = {}

    class Media:
        js = [cms_static_url(path) for path in (
            'js/libs/jquery.ui.core.js',
            'js/libs/jquery.ui.sortable.js',
            'js/plugin_editor.js',
        )]
        css = {
            'all': [cms_static_url(path) for path in (
                'css/plugin_editor.css',
            )]
        }

    def render(self, name, value, attrs=None):

        context = {
            'plugin_list': self.attrs['list'],
            'installed_plugins': self.attrs['installed'],
            'copy_languages': self.attrs['copy_languages'],
            'language': self.attrs['language'],
            'show_copy': self.attrs['show_copy'],
            'placeholder': self.attrs['placeholder'],
        }
        return mark_safe(render_to_string(
            'admin/cms/page/widgets/plugin_editor.html', context))

class UserSelectAdminWidget(Select):
    """Special widget used in page permission inlines, because we have to render
    an add user (plus) icon, but point it somewhere else - to special user creation
    view, which is accessible only if user haves "add user" permissions.

    Current user should be assigned to widget in form constructor as an user
    attribute.
    """
    def render(self, name, value, attrs=None, choices=()):
        output = [super(UserSelectAdminWidget, self).render(name, value, attrs, choices)]
        if hasattr(self, 'user') and (self.user.is_superuser or \
            self.user.has_perm(PageUser._meta.app_label + '.' + PageUser._meta.get_add_permission())):
            # append + icon
            add_url = '../../../cms/pageuser/add/'
            output.append(u' ' % \
                    (add_url, name))
            output.append(u'' % (CMS_ADMIN_ICON_BASE, _('Add Another')))
        return mark_safe(u''.join(output))

class PlaceholderPluginEditorWidget(PluginEditor):
    attrs = {}
    def __init__(self, request, filter_func):
        self.request = request
        self.filter_func = filter_func

    def __deepcopy__(self, memo):
        obj = copy.copy(self)
        obj.request = copy.copy(self.request)
        obj.filter_func = self.filter_func
        memo[id(self)] = obj
        return obj

    def render(self, name, value, attrs=None):
        try:
            ph = Placeholder.objects.get(pk=value)
        except Placeholder.DoesNotExist:
            ph = None
            context = {'add':True}
        if ph:
            plugin_list = ph.cmsplugin_set.filter(parent=None).order_by('position')
            plugin_list = self.filter_func(self.request, plugin_list)
            language = get_language_from_request(self.request)
            copy_languages = []
            if ph.actions.can_copy:
                copy_languages = ph.actions.get_copy_languages(
                    placeholder=ph,
                    model=ph._get_attached_model(),
                    fieldname=ph._get_attached_field_name()
                )
            context = {
                'plugin_list': plugin_list,
                'installed_plugins': plugin_pool.get_all_plugins(ph.slot, include_page_only=False),
                'copy_languages': copy_languages,
                'language': language,
                'show_copy': bool(copy_languages) and ph.actions.can_copy,
                'urloverride': True,
                'placeholder': ph,
            }
        #return mark_safe(render_to_string(
        #    'admin/cms/page/widgets/plugin_editor.html', context))
        return mark_safe(render_to_string(
            'admin/cms/page/widgets/placeholder_editor.html', context, RequestContext(self.request)))
<commit_msg>* make page widget choices lazy<commit_after># -*- coding: utf-8 -*-
from cms.forms.utils import get_site_choices, get_page_choices
from cms.models import Page, PageUser, Placeholder
from cms.plugin_pool import plugin_pool
from cms.utils import get_language_from_request, cms_static_url
from django.conf import settings
from django.contrib.sites.models import Site
from django.forms.widgets import Select, MultiWidget, Widget
from django.template.context import RequestContext
from django.template.loader import render_to_string
from django.utils.encoding import force_unicode
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext as _
import copy
from cms.templatetags.cms_admin import CMS_ADMIN_ICON_BASE

class PageSelectWidget(MultiWidget):
    """A widget that allows selecting a page by first selecting a site and then
    a page on that site in a two step process.
    """
    def __init__(self, site_choices=None, page_choices=None, attrs=None):
        if attrs is not None:
            self.attrs = attrs.copy()
        else:
            self.attrs = {}
        if site_choices is None or page_choices is None:
            from cms.forms.fields import SuperLazyIterator
            site_choices = SuperLazyIterator(get_site_choices)
            page_choices = SuperLazyIterator(get_page_choices)
        self.site_choices = site_choices
        self.choices = page_choices
        widgets = (Select(choices=site_choices ),
                   Select(choices=[('', '----')]),
                   Select(choices=self.choices, attrs={'style': "display:none;"} ),
        )
        super(PageSelectWidget, self).__init__(widgets, attrs)

    def decompress(self, value):
        """
        receives a page_id in value and returns the site_id and page_id
        of that page or the current site_id and None if no page_id is given.
        """
        if value:
            page = Page.objects.get(pk=value)
            site = page.site
            return [site.pk, page.pk, page.pk]
        site = Site.objects.get_current()
        return [site.pk,None,None]

    def _has_changed(self, initial, data):
        # THIS IS A COPY OF django.forms.widgets.Widget._has_changed()
        # (except for the first if statement)

        """
        Return True if data differs from initial.
        """
        # For purposes of seeing whether something has changed, None is
        # the same as an empty string, if the data or inital value we get
        # is None, replace it w/ u''.
        if data is None or (len(data)>=2 and data[1] in [None,'']):
            data_value = u''
        else:
            data_value = data
        if initial is None:
            initial_value = u''
        else:
            initial_value = initial
        if force_unicode(initial_value) != force_unicode(data_value):
            return True
        return False

    def render(self, name, value, attrs=None):
        # THIS IS A COPY OF django.forms.widgets.MultiWidget.render()
        # (except for the last line)

        # value is a list of values, each corresponding to a widget
        # in self.widgets.
        if not isinstance(value, list):
            value = self.decompress(value)
        output = []
        final_attrs = self.build_attrs(attrs)
        id_ = final_attrs.get('id', None)
        for i, widget in enumerate(self.widgets):
            try:
                widget_value = value[i]
            except IndexError:
                widget_value = None
            if id_:
                final_attrs = dict(final_attrs, id='%s_%s' % (id_, i))
            output.append(widget.render(name + '_%s' % i, widget_value, final_attrs))
        output.append(r'''''' % {'name': name})
        return mark_safe(self.format_output(output))

    def format_output(self, rendered_widgets):
        return u' '.join(rendered_widgets)

class PluginEditor(Widget):
    def __init__(self, attrs=None):
        if attrs is not None:
            self.attrs = attrs.copy()
        else:
            self.attrs = {}

    class Media:
        js = [cms_static_url(path) for path in (
            'js/libs/jquery.ui.core.js',
            'js/libs/jquery.ui.sortable.js',
            'js/plugin_editor.js',
        )]
        css = {
            'all': [cms_static_url(path) for path in (
                'css/plugin_editor.css',
            )]
        }

    def render(self, name, value, attrs=None):

        context = {
            'plugin_list': self.attrs['list'],
            'installed_plugins': self.attrs['installed'],
            'copy_languages': self.attrs['copy_languages'],
            'language': self.attrs['language'],
            'show_copy': self.attrs['show_copy'],
            'placeholder': self.attrs['placeholder'],
        }
        return mark_safe(render_to_string(
            'admin/cms/page/widgets/plugin_editor.html', context))

class UserSelectAdminWidget(Select):
    """Special widget used in page permission inlines, because we have to render
    an add user (plus) icon, but point it somewhere else - to special user creation
    view, which is accessible only if user haves "add user" permissions.

    Current user should be assigned to widget in form constructor as an user
    attribute.
    """
    def render(self, name, value, attrs=None, choices=()):
        output = [super(UserSelectAdminWidget, self).render(name, value, attrs, choices)]
        if hasattr(self, 'user') and (self.user.is_superuser or \
            self.user.has_perm(PageUser._meta.app_label + '.' + PageUser._meta.get_add_permission())):
            # append + icon
            add_url = '../../../cms/pageuser/add/'
            output.append(u' ' % \
                    (add_url, name))
            output.append(u'' % (CMS_ADMIN_ICON_BASE, _('Add Another')))
        return mark_safe(u''.join(output))

class PlaceholderPluginEditorWidget(PluginEditor):
    attrs = {}
    def __init__(self, request, filter_func):
        self.request = request
        self.filter_func = filter_func

    def __deepcopy__(self, memo):
        obj = copy.copy(self)
        obj.request = copy.copy(self.request)
        obj.filter_func = self.filter_func
        memo[id(self)] = obj
        return obj

    def render(self, name, value, attrs=None):
        try:
            ph = Placeholder.objects.get(pk=value)
        except Placeholder.DoesNotExist:
            ph = None
            context = {'add':True}
        if ph:
            plugin_list = ph.cmsplugin_set.filter(parent=None).order_by('position')
            plugin_list = self.filter_func(self.request, plugin_list)
            language = get_language_from_request(self.request)
            copy_languages = []
            if ph.actions.can_copy:
                copy_languages = ph.actions.get_copy_languages(
                    placeholder=ph,
                    model=ph._get_attached_model(),
                    fieldname=ph._get_attached_field_name()
                )
            context = {
                'plugin_list': plugin_list,
                'installed_plugins': plugin_pool.get_all_plugins(ph.slot, include_page_only=False),
                'copy_languages': copy_languages,
                'language': language,
                'show_copy': bool(copy_languages) and ph.actions.can_copy,
                'urloverride': True,
                'placeholder': ph,
            }
        #return mark_safe(render_to_string(
        #    'admin/cms/page/widgets/plugin_editor.html', context))
        return mark_safe(render_to_string(
            'admin/cms/page/widgets/placeholder_editor.html', context, RequestContext(self.request)))
<|endoftext|>