def boolean_gating(gate_params): points = gate_params['points'] points2 = gate_params['1'] boolean_op = gate_params['0'] reverse_gate = '0' if 'reverse' in gate_params: if (gate_params['reverse']): reverse_gate = '1' ## Generate unique datastore path, ensuring uniqueness. while True: new_name = str(uuid1()) new_path = ds.generate_path(DATA_BUCKET, None, new_name) if not ds.check_exists(new_path, None): break if (gate_params['tool'] == "boolean_gating"): if (len(points)%2 == 0) and (len(points2)%2 == 0): if (reverse_gate == '1'): if (boolean_op == 'or'): boolean_op = 'and' elif (boolean_op == 'and'): boolean_op = 'or' else: return generate_gating_feedback("fail", "The boolean operator must be either 'and' or 'or'") gate1_points = " ".join(str(p) for p in points) gate2_points = " ".join(str(p) for p in points2) queue.gate_boolean(gate_params['filename'], new_name, boolean_op, 'poly', gate1_points, reverse_gate, 'poly', gate2_points, reverse_gate, gate_params['axes']['x'], gate_params['axes']['y'], gate_params['axes']['x'], gate_params['axes']['y']); return generate_gating_feedback("success", "the boolean gating was performed correctly", new_name, gate_params['filename'], gate_params['axes']['x'], gate_params['axes']['y']) else: return generate_gating_feedback("fail", "notcorrect, wrong number of arguments")
def new_file(self, field_name, file_name, content_type, content_length, charset): ## Generate unique datastore path, ensuring uniqueness. while True: self.name = str(uuid1()) path = ds.generate_path(buckets.DATA + "/", None, self.name) if not ds.check_exists(path, None): break ## Generate friendly name. friendly_name = splitext(file_name)[0] ## Setup file handle. self.file_handle = ds.add_file(path, friendly_name, "raw_data", "w") ## Setup uploaded file. self.upload = fcsUploadedFile(path, self.name, content_type, charset) return None
def change_axes(tool_params): ## Generate unique datastore path, ensuring uniqueness. while True: new_name = str(uuid1()) new_path = ds.generate_path(DATA_BUCKET, None, new_name) if not ds.check_exists(new_path, None): break if tool_params['newAxes']['x'] == tool_params['newAxes']['y']: return generate_gating_feedback("fail", "Please choose two different axes") # todo: check if the axes exist. queue.change_axis(tool_params['filename'], tool_params['newAxes']['x'], tool_params['newAxes']['y'], new_name) return generate_gating_feedback("success","the axis change was performed", new_name, tool_params['filename'], tool_params['newAxes']['x'], tool_params['newAxes']['y'])
def analysis_status_json(request): authed_user = auth.get_current_user() if authed_user is None: return __unauthed_response() user_key = ps.get_user_key_by_id(authed_user.user_id()) response_part = { 'backoff' : 0, #tells the client to back off for a given amount of time (milliseconds) (This is added to the client's constant poll interval) 'giveup' : True, #True instructs the client to stop polling - useful for situations such as unauthed requests where polling will never result in the user being shown a graph 'done' : False #True indicates that the analysis has finished and that the user can be redirected to the new image } try: file_req = json.loads(request.raw_post_data) except ValueError: response_part.update({'error' : 'Invalid request payload.'}) return HttpResponse(json.dumps(response_part), content_type="application/json") if 'filename' not in file_req: response_part.update({'error' : 'Incomplete request.'}) return HttpResponse(json.dumps(response_part), content_type="application/json") chk_file_name = DATA_BUCKET + '/' + file_req['filename'] file_entry = ps.get_file_by_name(chk_file_name) logging.info(file_entry) if file_entry is None: response_part.update( { 'error' : 'File or gate not recognised.', 'giveup' : False } ) return HttpResponse(json.dumps(response_part), content_type="application/json") else: fp_entry = ps.get_user_file_permissions(file_entry.key, user_key) if fp_entry is None: response_part.update( { 'error' : 'Permission denied.' } ) return HttpResponse(json.dumps(response_part), content_type="application/json") name = file_req['filename'] is_done = ds.check_exists(GRAPH_BUCKET + '/' + name + '.png', None) #Prevent redirecting before the view is ready is_done &= ds.check_exists(DATA_BUCKET + '/' + name, None) #Prevent redirecting before gating info is ready is_done &= ds.check_exists(INFO_BUCKET + '/' + name + '.txt', None) response_part.update( { 'done' : is_done, 'giveup' : False } ) return HttpResponse(json.dumps(response_part), content_type="application/json")
def graph_preview(request, file = None): lst = ds.list(DATA_BUCKET) for temp_file in lst: temp_file.filename = temp_file.filename.rpartition('/')[2] if temp_file.filename == file: file_info = temp_file; return render(request, 'graph_preview.html', {'current_file' : file_info, 'file_name_without_extension' : file})
def file_list_json(request): app_access = __check_app_access() if app_access is not None: return app_access authed_user = auth.get_current_user() user_key = ps.get_user_key_by_id(authed_user.user_id()) #TODO: This shouldn't be here - a generic method in APIPermissions would be nice. # 'your files' file_list = [] lst = ps.get_user_permissions_list(user_key) temp_group = [] if lst is not None: for perm in lst: list_entry = {} file_entry = ps.get_file_by_key(perm.file_key) if file_entry is not None: temp_file = ds.get_file_info(file_entry.file_name) if temp_file is None: continue list_entry.update({ 'permissions' : 'yes', 'friendlyName' : file_entry.friendly_name, 'colour' : perm.colour, 'starred' : perm.starred } ) temp_file.filename = temp_file.filename.rpartition('/')[2] list_entry.update( { 'filename' : temp_file.filename, 'size' : temp_file.st_size, 'hash' : temp_file.etag, 'timestamp' : temp_file.st_ctime }) temp_group.append(list_entry) if len(temp_group) > 0: file_list.append({ 'catagory' : 'owned', 'heading' : 'Your Files', 'type' : 'files', 'data' : temp_group }) if len(file_list) == 0: file_list.append({ 'catagory' : 'notice', 'type' : 'html', # TODO: move this line out 'data' : '<a data-toggle="modal" data-target="#uploadModal" class="list-group-item">No files - Click here to upload one</a>' }) return HttpResponse(json.dumps(file_list), content_type="application/json")
def fetch_file(path, type, friendly): # TODO: Need protection against hack such as ../ buffer = ds.open(path) if buffer: file = buffer.read() # TODO: Maybe transform the httpresponse to streaminghttpresponse in case the graph is really large and to improve efficiency response = HttpResponse(file, content_type=type) # Get filename. if friendly: path = path.rpartition('/')[0] + '/' + ps.get_file_by_name(path).friendly_name # Construct and send response response['Content-Disposition'] = 'attachment; filename="' + path + '"' return response else: return HttpResponseNotFound('<h1>404 : ' + path + ' not found</h1>')
def multiple_gating(gate_params): points = gate_params['points'] while True: new_name = str(uuid1()) new_path = ds.generate_path(DATA_BUCKET, None, new_name) if not ds.check_exists(new_path, None): break if (gate_params['tool'] == 'kmeans_gating') : if len(points) == 1 : clusters = new_name number_gates = points[0] new_names = [new_name] for i in range(0, number_gates-1): while True: next_new_name = str(uuid1()) path = ds.generate_path(DATA_BUCKET, None, next_new_name) if not ds.check_exists(path, None): new_names.append(next_new_name) clusters = next_new_name + " " + clusters break queue.gate_kmeans(gate_params['filename'], clusters, str(number_gates), gate_params['axes']['x'], gate_params['axes']['y']); return generate_gating_feedback("success", "the kmeans gate was performed correctly", new_names, gate_params['filename'], gate_params['axes']['x'], gate_params['axes']['y']) else: return generate_gating_feedback("fail", "notcorrect, wrong number of arguments") elif (gate_params['tool'] == 'quadrant_gating') : if len(points) == 2 : other_new_names = [] for i in range(0, 3): while True: next_new_name = str(uuid1()) path = ds.generate_path(DATA_BUCKET, None, next_new_name) if not ds.check_exists(path, None): other_new_names.append(next_new_name) break x_coord = str(points[0]) y_coord = str(points[1]) queue.gate_quadrant(gate_params['filename'], x_coord, y_coord, new_name, other_new_names[0], other_new_names[1], other_new_names[2], gate_params['axes']['x'], gate_params['axes']['y']); new_paths = [new_name] + other_new_names new_paths.reverse() #Make sure the user polls for the last graph to be created return generate_gating_feedback("success", "the quadrant gate was performed correctly", new_paths, gate_params['filename'], gate_params['axes']['x'], gate_params['axes']['y']) else: return generate_gating_feedback("fail", "notcorrect, wrong number of arguments")
def app(request): lst = ds.list(DATA_BUCKET) file_info = None app_access = __check_app_access(True) if app_access is not None: return app_access authed_user = auth.get_current_user() authed_user_nick = authed_user.nickname() request.upload_handlers = [upload_handling.fcsUploadHandler()] if request.method == 'POST': form = forms.UploadFile(request.POST, request.FILES) if form.is_valid(): cd = form.cleaned_data return redirect('#!/preview/' + request.FILES['file'].name) else: return render(request, 'app.html', {'form': form, 'files' : lst , 'current_file' : file_info, 'authed_user_nick' : authed_user_nick}) else: form = forms.UploadFile() return render(request, 'app.html', {'form': form, 'files' : lst , 'current_file' : file_info, 'authed_user_nick' : authed_user_nick})
def file_list(request): app_access = __check_app_access() if app_access is not None: return app_access lst = ds.list(DATA_BUCKET) file_list = [] for temp_file in lst: list_entry = {} file_entry = permissions.get_file_by_name(temp_file.filename) if file_entry is not None: list_entry.update({ 'permissions' : 'yes' }) else: list_entry.update({ 'permissions' : 'no' }) temp_file.filename = temp_file.filename.rpartition('/')[2] list_entry.update( { 'filestat' : temp_file } ) file_list.append(list_entry) return render(request, 'file_list.html', {'files' : file_list})
def test_addfile_checkExists(self): ds.add_file("/test_bucket/test_dir/test_file.ext") self.assertTrue(ds.check_exists("/test_bucket/test_dir/test_file.ext", None))
def file_preview(request, file = None): app_access = __check_app_access() if app_access is not None: return app_access ## Authentication. authed_user = auth.get_current_user() if authed_user is None: authed_user_nick = 'Guest' else: authed_user_nick = authed_user.nickname() ## Graph visualisation. # Replaced by a spinning canvas on the clientside # if not ds.check_exists(GRAPH_BUCKET + '/' + file_name_without_extension + '.png', None): # file_name_without_extension = None #TODO: Might need to be simplified or moved to a function in fileinfo # TODO the folowing should be replaced by a method in the APIDatastore file_info = ps.get_file_by_name(DATA_BUCKET + '/' + file) undo_uri = None if file_info is not None: prev_file = ps.get_file_by_key(file_info.prev_file_key) if prev_file is not None: undo_uri = prev_file.file_name.rpartition(DATA_BUCKET + '/')[2] lst = ds.list(DATA_BUCKET) current_file = None for temp_file in lst: temp_file.filename = temp_file.filename.rpartition('/')[2] if temp_file.filename == file: current_file = temp_file; # Check whether graph exists yet. graph_exists = ds.check_exists(GRAPH_BUCKET + '/' + file.partition('.')[0] + '.png', None) # Get permissions for file. permissions = None if file_info is not None: user_key = ps.get_user_key_by_id(authed_user.user_id()) permissions = ps.get_user_file_permissions(file_info.key, user_key) template_dict = {'current_file' : current_file, 'name' : file, 'authed_user_nick': authed_user_nick, 'file_info' : file_info, 'graph_ready' : graph_exists, 'undo_link' : undo_uri, 'permissions' : permissions } ## Get gating information. info_path = INFO_BUCKET + '/' + file.partition('.')[0] + '.txt' if ds.check_exists(info_path, None): buffer = ds.open(info_path) if buffer: file_text = buffer.read() stats = file_text.split(' ') if len(stats)>=3: template_dict.update( { 'gating_stats' : { 'selection' : stats[0], 'total' : stats[1], 'percent' : float(stats[2])*100 } } ) ## Get different axis axis_path = INFO_BUCKET + '/' + file.partition('.')[0] + 'info.txt' if ds.check_exists(axis_path, None): buffer = ds.open(axis_path) if buffer: file_text = buffer.read() axis = file_text.split('\n') if len(axis)>0: while '' in axis: axis.remove('') template_dict.update( { 'available_axes' : axis } ) return render(request, 'file_preview.html', template_dict)
def file_list_edit(request): authed_user = auth.get_current_user() if authed_user is None: return __unauthed_response() user_key = ps.get_user_key_by_id(authed_user.user_id()) try: actions = json.loads(request.raw_post_data) except ValueError: return HttpResponse(json.dumps({'error' : 'invalid request payload'}), content_type="application/json") if not isinstance(actions, list): return HttpResponse(json.dumps({'error' : 'Payload is not a list'}), content_type="application/json") res = [] for a in actions: #We can't do anything without a filename if 'filename' not in a: continue else: filename = a['filename'] if 'action' not in a: continue else: action = a['action'] res_fragment = { 'filename' : a['filename'], 'action' : a['action'] } if action == 'delete': file_entry = ps.get_file_by_name(DATA_BUCKET + '/' + filename) if file_entry is not None: ps.remove_file_by_key(file_entry.key) ds.delete(DATA_BUCKET + '/' + filename) ds.delete(INFO_BUCKET + '/' + filename + 'info.txt') ds.delete(INFO_BUCKET + '/' + filename + '.txt') ds.delete(GRAPH_BUCKET + '/' + filename + '.png') res_fragment.update( { 'success' : True } ) #Reinstate this when CE PAL is available #else: #res_fragment.update( { 'success' : False, 'error' : 'File does not exist.' } ) elif action == 'rename': if 'newname' not in a: res_fragment.update( { 'success' : False, 'error' : 'New name not specified' } ) else: file_entry = ps.get_file_by_name(DATA_BUCKET + '/' + filename) if file_entry is None: res_fragment.update( { 'success' : False, 'error' : 'File does not exist.' } ) else: file_entry.friendly_name = a['newname'] if ps.update_file(file_entry): res_fragment.update( { 'success' : True } ) else: res_fragment.update( { 'success' : False, 'error' : 'Could not rename file' } ) elif action == 'star' or action == 'unstar': file_entry = ps.get_file_by_name(DATA_BUCKET + '/' + filename) if file_entry is None: res_fragment.update( { 'success' : False, 'error' : 'File does not exist.' } ) else: fp_entry = ps.get_user_file_permissions(file_entry.key, user_key) if fp_entry is None: res_fragment.update( { 'success' : False, 'error' : 'Permissions entry not found' } ) else: if ps.modify_file_permissions_by_key(fp_entry.key, new_starred = (action == 'star')): res_fragment.update( { 'success' : True } ) else: res_fragment.update( { 'success' : False, 'error' : 'Could not update file' } ) elif action == 'recolour': if 'newcolour' not in a: res_fragment.update( { 'success' : False, 'error' : 'New colour not specified' } ) else: colour = a['newcolour'] chk_string = re.compile("^[A-Fa-f0-9]{6}$") if (chk_string.match(colour)): file_entry = ps.get_file_by_name(DATA_BUCKET + '/' + filename) if file_entry is None: res_fragment.update( { 'success' : False, 'error' : 'File does not exist.' } ) else: fp_entry = ps.get_user_file_permissions(file_entry.key, user_key) if fp_entry is None: res_fragment.update( { 'success' : False, 'error' : 'Permissions entry not found' } ) else: if ps.modify_file_permissions_by_key(fp_entry.key, new_colour = colour): res_fragment.update( { 'success' : True } ) else: res_fragment.update( { 'success' : False, 'error' : 'Could not update file' } ) else: res_fragment.update( { 'success' : False, 'error' : 'New colour invalid' } ) else: res_fragment.update( { 'success' : False, 'error' : 'Action not recognised' } ) res.append(res_fragment) return HttpResponse(json.dumps(res), content_type="application/json")
def test_addfile_alreadyExists(self): ds.add_file("/test_bucket/test_dir/test_file_2.ext"); self.assertFalse(ds.add_file("/test_bucket/test_dir/test_file2.ext"))
def test_addfile_checkCont(self): ds.add_file("/test_bucket/test_dir/test_file_3.ext", "testing-testing-testing", None) fh = ds.open("/test_bucket/test_dir/test_file_3.ext", 'r') self.assertEqual(fh.read(), "testing-testing-testing")
def test_getcontainer_bucketroot(self): self.assertEqual(ds.get_container("/dir/"), "/dir/")
def test_checkexists_notExistDir(self): self.assertFalse(ds.check_exists("/some_bucket/not_a_real_dir/", None))
def close(self): ds.close(self.file_handle)
def test_getcontainer_filename(self): self.assertEqual(ds.get_container("/dir/subdir/file.ext"), "/dir/subdir/")
def test_getcontainer_slash(self): self.assertEqual(ds.get_container("/"), "/")
def test_getcontainer_empty(self): self.assertEqual(ds.get_container(""), "/")
def simple_gating(gate_params): points = gate_params['points'] reverse_gate = '0' if 'reverse' in gate_params: if (gate_params['reverse']): reverse_gate = '1' ## Generate unique datastore path, ensuring uniqueness. while True: new_name = str(uuid1()) new_path = ds.generate_path(DATA_BUCKET, None, new_name) if not ds.check_exists(new_path, None): break if (gate_params['tool'] == "rectangular_gating") : if len(points) == 4 : #Reoder the point to take the topLeft and bottomRight points of the square if points[0] > points[2]: tempcoor = points[0] points[0] = points[2] points[2] = tempcoor if points[1] > points[3]: tempcoor = points[1] points[1] = points[3] points[3] = tempcoor gating_request = " ".join(str(p) for p in points) queue.gate_rectangle(gate_params['filename'], gating_request, new_name, reverse_gate, gate_params['axes']['x'], gate_params['axes']['y']); return generate_gating_feedback("success", "the rectangular gating was performed correctly", new_name, gate_params['filename'], gate_params['axes']['x'], gate_params['axes']['y']) else: return generate_gating_feedback("fail", "notcorrect " + params + " length:" + str(len(points)) + " is not equal to 4") elif (gate_params['tool'] == "polygon_gating") : if len(points)%2 == 0 : gating_request = " ".join(str(p) for p in points) queue.gate_polygon(gate_params['filename'], gating_request, new_name, reverse_gate, gate_params['axes']['x'], gate_params['axes']['y']); return generate_gating_feedback("success", "the polygonal gating was performed correctly", new_name, gate_params['filename'], gate_params['axes']['x'], gate_params['axes']['y']) else: return generate_gating_feedback("fail", "notcorrect " + params + " #pointCoordinates:" + str(len(points))-1 + " is not pair") elif (gate_params['tool'] == "oval_gating") : if len(points) == 6 : gating_request = " ".join(str(p) for p in points) queue.gate_circle(gate_params['filename'], gating_request, new_name, reverse_gate, gate_params['axes']['x'], gate_params['axes']['y']); return generate_gating_feedback("success", "the oval gating was performed correctly", new_name, gate_params['filename'], gate_params['axes']['x'], gate_params['axes']['y']) else: return generate_gating_feedback("fail", "notcorrect " + params + " #pointCoordinates:" + str(len(points)) + " is not even") elif (gate_params['tool'] == 'normal_gating') : if len(points) == 1 : gating_request = str(points[0]) queue.gate_normal(gate_params['filename'], new_name, reverse_gate, gate_params['axes']['x'], gate_params['axes']['y'], gating_request); return generate_gating_feedback("success", "the normal gating was performed correctly", new_name, gate_params['filename'], gate_params['axes']['x'], gate_params['axes']['y']) else: return generate_gating_feedback("fail", "notcorrect, wrong number of arguments") else : return generate_gating_feedback("fail", "The gate " + gate_params['tool'] + " is not known")
def open(self, mode=None): if mode is not None: self.mode = mode self.file_handle = ds.open(self.path, self.mode) return self.file_handle
def test_checkexists_notExist(self): self.assertFalse(ds.check_exists("/some_bucket/no_file/here/file.notafile", None))
def test_getcontainer_dirname(self): self.assertEqual(ds.get_container("/dir/subdir"), "/dir/")