Example #1
0
    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")
Example #2
0
    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)
Example #3
0
    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)
Example #4
0
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
Example #5
0
    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))
Example #6
0
    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))
Example #7
0
    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
Example #8
0
    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))
Example #9
0
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())