def post(self, user_id): point = (int(self.request.get("x")), int(self.request.get("y"))) image_key = self.request.get("image_key") img_obj = ImageObject.get_by_id(int(image_key), parent=db_parent) picks = Picks.all().ancestor(img_obj) picks = picks.filter("user_id =", user_id).get() if not picks: # Then the user has not picked # this image before so start # some picks for this user. picks = Picks(user_id=user_id, picks=json.dumps([point]).encode(), parent=img_obj) picks.put() img_obj.put() else: # Then carry on adding picks. all_picks = json.loads(picks.picks) all_picks.append(point) picks.picks = json.dumps(all_picks).encode() picks.put() self.response.write("Ok")
def get(self): user_id = users.get_current_user().user_id() image_key = self.request.get("image_key") img_obj = ImageObject.get_by_id(int(image_key), parent=db_parent) # DO THE MAGIC! image = get_result_image(img_obj) picks = Picks.all().ancestor(img_obj).fetch(1000) pick_users = [p.user_id for p in picks] count = len(pick_users) owner_user = img_obj.user_id # Filter out the owner and current user if user_id in pick_users: pick_users.remove(user_id) if owner_user in pick_users: pick_users.remove(owner_user) # Get a list of comment strings, if any. comments = Comment.all().ancestor(img_obj).order('datetime').fetch( 1000) params = self.get_base_params(count=count, image=image, img_obj=img_obj, user_id=user_id, owner_user=owner_user, pick_users=pick_users, comments=comments) template = env.get_template("results.html") html = template.render(params) self.response.write(html)
def delete(self, user_id): image_key = self.request.get("image_key") image_obj = ImageObject.get_by_id(int(image_key), parent=db_parent) if ((image_obj.user_id == user_id) or (users.is_current_user_admin())): self.response.headers["Content-Type"] = "application/json" if not Picks.all().ancestor(image_obj).get(): # Then there are no intepretations, so anyone can delete. image_obj.delete() self.response.write(json.dumps({"success": True})) else: # There are interpretations. if users.is_current_user_admin(): # Then you can delete all the same. image_obj.delete() self.response.write(json.dumps({"success": True})) else: self.response.write(json.dumps({"interpretations": True})) else: self.error(500)
def statistics(): stats = { "user_count": User.all().count(), "image_count": ImageObject.all().count(), "pick_count": Picks.all().count(), "vote_count": Vote.all().count() } return stats
def get(self, user_id): """ Request the total number of votes for a particular interpreter's interpretation for a given image, and the value of the current user's choice. E.g. user_id: kwinkunks user: [email protected] (interpreter) image_key: Brazil.png (of course we provide keys, not plain text) result: {"votes": 12, "user_choice": -1 } So the [email protected]'s pick on that image has 12 votes total, and kwinkunks voted -1. """ self.response.headers["Content-Type"] = "application/json" interpreter_id = self.request.get("user") image_key = int(self.request.get("image_key")) # Get the image, and then its picks. # Then filter back to the requested # interpreter's pick. img = ImageObject.get_by_id(image_key, parent=db_parent) picks = Picks.all().ancestor(img) pick = picks.filter("user_id =", interpreter_id).get() # Get the total votes for this pick. votes = pick.votes # Get all the votes for this pick, # then filter back to this user's votes. user_votes = Vote.all().ancestor(pick) user_vote = user_votes.filter("user_id =", user_id).get() # Figure out what this user voted. if not user_vote: user_choice = 0 else: user_choice = user_vote.value # Build a dict to send back. data = {"votes": votes, "user_choice": user_choice} self.response.write(json.dumps(data))
def delete(self, user_id): image_key = self.request.get("image_key") img_obj = ImageObject.get_by_id(int(image_key), parent=db_parent) data = Picks.all().ancestor(img_obj).filter("user_id =", user_id) data = data.get() points = json.loads(data.picks) if self.request.get("clear"): data.delete() value = [] img_obj.put() elif self.request.get("undo"): value = points.pop() data.picks = json.dumps(points).encode() data.put() self.response.write(json.dumps(value))
def get(self, user_id): image_key = self.request.get("image_key") img_obj = ImageObject.get_by_id(int(image_key), parent=db_parent) if self.request.get("all"): data = Picks.all().ancestor(img_obj) self.response.write(data) return if self.request.get("user_picks"): # Write out the picks belonging to the # requesting user. data = Picks.all().ancestor(img_obj) data = data.filter("user_id =", user_id).get() if data: picks = data.picks else: picks = json.dumps([]) self.response.write(picks) return if self.request.get("user"): # Write out the picks for a specific user, # along with some flags to decide on # display colour (set in pick-drawing.js). # Filter out current user's first... user_data = Picks.all().ancestor(img_obj).filter( "user_id =", user_id).get() # Now get the owner's... owner_id = img_obj.user_id owner_data = Picks.all().ancestor(img_obj).filter( "user_id =", owner_id).get() # Finally get everyone else's. pick_user_id = self.request.get("user") other_data = Picks.all().ancestor(img_obj).filter( "user_id =", pick_user_id).get() # Deal with getting None if other_data: other_data = json.loads(other_data.picks) else: other_data = json.loads('[]') if owner_data: owner_data = json.loads(owner_data.picks) else: owner_data = json.loads('[]') # There should always be user data # But maybe not for admins... if user_data: user_data = json.loads(user_data.picks) else: user_data = json.loads('[]') # Might as well set owner user # AND current user flags. Display logic # is in pick-drawing.js # Should no longer need to do this... owner, current = False, False if (user_id == pick_user_id): current = True if (owner_id == pick_user_id): owner = True output = { "data": other_data, "owner_data": owner_data, "user_data": user_data, "owner": owner, "current": current } self.response.headers["Content-Type"] = "application/json" self.response.write(json.dumps(output)) return
def post(self, user_id): """ Post a change to the total number of votes for a particular interpretation for a given image, and the value of the current user's choice. E.g. user_id: kwinkunks user: [email protected] (interpreter) image_key: Brazil.png vote:-1 (of course we provide keys, not plain text) result: {"votes": 12, "user_choice": -1 } So kwinkunks voted -1 on the [email protected]'s pick on that image, and it now has 12 votes total. """ self.response.headers["Content-Type"] = "application/json" interpreter_id = self.request.get("user") update_vote = int(self.request.get("vote")) img_key = int(self.request.get("image_key")) user = users.get_current_user() img = ImageObject.get_by_id(img_key, parent=db_parent) # Get the image's picks, then filter # down to the specified interpreter's pick. picks = Picks.all().ancestor(img) pick = picks.filter("user_id =", interpreter_id).get() # Check if this user is the interpreter; # if not, set a vote value. if user_id == interpreter_id: update_vote = 0 # A self-vote, not allowed elif update_vote > 0: update_vote = 1 # An upvote else: update_vote = -1 # A downvote # Get all the votes for this pick, # then filter to this user's vote. votes = Vote.all().ancestor(pick) vote = votes.filter("user_id =", user_id).get() # If this is their first vote, make a new # Vote object. if vote is None: vote = Vote(user_id=user_id, value=update_vote, parent=pick) else: # We are updating the existing vote; # reset if they try to set to the same vote if vote.value == update_vote: vote.value = 0 else: vote.value = update_vote # Write the vote object to the db. vote.put() # Build the dict to send back. data = {"votes": pick.votes, "user_choice": vote.value} self.response.write(json.dumps(data))
def get_result_image(img_obj, opacity_scalar=None): """ Takes an image, gets its interpretations, and makes a new image that shows all the interpretations concatenated. Maps a 'heatmap' colourbar to the result. Returns the new 'heatmap' image, plus a count of interpretations. """ # Read the interpretations for this image. data = Picks.all().ancestor(img_obj).fetch(1000) # Get the dimensions. w, h = img_obj.width, img_obj.height avg = (w + h) / 2. # Make an 'empty' image for all the results. heatmap_image = np.zeros((h, w)) alpha_image = np.ones_like(heatmap_image) # get total number of votes on this challenge total_votes = 0 top_vote = 0 for user in data: total_votes += user.votes if user.votes > top_vote: top_vote = user.votes # Now loop over the interpretations and sum into that empty image. for user in data: # get the number of votes this interpretation has nvotes = user.votes # Make a new image for this interpretation. user_image = np.zeros((h, w)) # Get the points. picks = np.array(json.loads(user.picks)) print picks if img_obj.pickstyle == 'polygons': picks = np.append(picks, picks[0]).reshape(picks.shape[0] + 1, picks.shape[1]) # Sort on x values. #picks = picks[picks[:,0].argsort()] # This needs refactoring! # Deal with the points, and set the # radius of the disk structuring element. if img_obj.pickstyle != 'points': for i in range(picks.shape[0] - 1): xpair = picks[i:i + 2, 0] if xpair[0] > xpair[1]: xpair = xpair[xpair[:].argsort()] xrev = True else: xrev = False ypair = picks[i:i + 2, 1] print " ++ IN THE LOOP ++ " print xpair, ypair if ypair[0] > ypair[1]: ypair = ypair[ypair[:].argsort()] yrev = True else: yrev = False # Do the interpolation x, y = interpolate(xpair, ypair) if xrev: # then need to unreverse... x = x[::-1] if yrev: # then need to unreverse... y = y[::-1] # Build up the image user_image[(y, x)] = 1. n = np.ceil(avg / 300.).astype(int) else: x, y = picks[:, 0], picks[:, 1] user_image[(y, x)] = 1. n = np.ceil(avg / 150.).astype( int) # The radius of the disk structuring element # Dilate this image. dilated_image = dilate(user_image.astype(int), B=sedisk(r=n)) heatmap_image += dilated_image # Add it to the running summed image. if opacity_scalar == 'votes': if nvotes > -5: alpha_image += dilated_image * (nvotes + 5) / (top_vote + 5) elif opacity_scalar == 'rep': # Do something else pass else: pass # Normalize the heatmap from 0-255 for making an image. # More muted version: Subtract 1 first to normalize to # the non-zero data only. heatmap_norm = normalize(heatmap_image, 255) alpha_norm = normalize(alpha_image, 255) # Make the RGB channels. r = np.clip((2 * heatmap_norm), 0, 255) g = np.clip(((3 * heatmap_norm) - 255), 0, 255) b = np.clip(((3 * heatmap_norm) - 510), 0, 255) a = alpha_norm # Set everything corresponding to zero data to transparent. a[heatmap_image == 0] = 0 # Make the 4-channel image from an array. im = np.dstack([r, g, b, a]) im_out = Image.fromarray(im.astype('uint8'), 'RGBA') # Save out into file-like. output = StringIO.StringIO() im_out.save(output, 'png') return base64.b64encode(output.getvalue())