def create_classification_linking_form(): """ Create a new ClassificationLinkingForm instance. """ workspace_pid = settings.ONTOLOGY_DUMMY_PROJECT_ID root_links = get_classification_links_qs(workspace_pid, [], True) # Make sure we use no classification graph more than once known_roots = [] root_ids = [] for link in root_links: if link.class_instance_b.id not in known_roots: known_roots.append(link.class_instance_b.id) root_ids.append(link.id) class ClassificationLinkingForm(forms.Form): # A check-box for each project, checked by default classification_graph_suggestions = forms.MultipleChoiceField( required=False, widget=forms.CheckboxSelectMultiple(), help_text= "Only selected classification graphs will be linked to the new projects." ) additional_links = forms.ModelMultipleChoiceField( required=False, widget=FilteredSelectMultiple('Classification roots', is_stacked=False), queryset=ClassInstanceClassInstanceProxy.objects.filter( id__in=root_ids)) return ClassificationLinkingForm
def create_classification_linking_form(): """ Create a new ClassificationLinkingForm instance. """ workspace_pid = settings.ONTOLOGY_DUMMY_PROJECT_ID root_links = get_classification_links_qs(workspace_pid, [], True) # Make sure we use no classification graph more than once known_roots = [] root_ids = [] for link in root_links: if link.class_instance_b.id not in known_roots: known_roots.append(link.class_instance_b.id) root_ids.append(link.id) class ClassificationLinkingForm(forms.Form): # A check-box for each project, checked by default classification_graph_suggestions = forms.MultipleChoiceField( required=False, widget=forms.CheckboxSelectMultiple(), help_text="Only selected classification graphs will be linked to the new projects.", ) additional_links = forms.ModelMultipleChoiceField( required=False, widget=FilteredSelectMultiple("Classification roots", is_stacked=False), queryset=ClassInstanceClassInstanceProxy.objects.filter(id__in=root_ids), ) return ClassificationLinkingForm
def generate_tag_groups(add_supersets=True, respect_superset_graphs=False): """ This creates a tag sets dictionary. It ignores projects without any tags. """ project_ids, tag_sets, tag_supersets = get_tag_sets(add_supersets) # Get a query set that retrieves all CiCi links for all project ids at once workspace = settings.ONTOLOGY_DUMMY_PROJECT_ID links_qs = get_classification_links_qs(workspace, project_ids) # Make sure the the project ids and the classification root ids are # prefetched links_qs = links_qs.select_related('class_instance_a__project__id', 'class_instance_b__id') # Execute the query set to build a look up table projects_to_cls_links = {} for cici in links_qs: if cici.class_instance_a.project.id not in projects_to_cls_links: projects_to_cls_links[cici.class_instance_a.project.id] = set() projects_to_cls_links[cici.class_instance_a.project.id].add( cici.class_instance_b.id) # Test which groups of projects belonging to a particular tag group, # have non-uniform classification graph links # TODO: Test for independent *and* dependent workspace available_tag_groups = {} for tags, projects in tag_sets.items(): differs = False cg_roots = set() projects_cgroots = {} # Collect all classification roots in this tag group for p in projects: try: # Get set of CiCi links for current project croots = projects_to_cls_links[p.id] except KeyError: # Use an empty set if there are no CiCi links for the # current project. croots = set() # Remember roots for this projects projects_cgroots[p] = { 'linked': croots, 'missing': [], 'workspace': workspace, } # Add classification graphs introduced by supersets to the expected # graphs in this tag set. if p not in tag_supersets[tags] or respect_superset_graphs: cg_roots.update(croots) # Check if there are updates needed for some projects num_differing = 0 meta = [] for p in projects_cgroots: croots = projects_cgroots[p]['linked'] diff = cg_roots - croots if len(diff) > 0: differs = True projects_cgroots[p]['missing'] = diff num_differing = num_differing + 1 strdiff = ", ".join([str(cg) for cg in diff]) meta.append("[PID: %s Missing: %s]" % (p.id, strdiff)) # If there is a difference, offer this tag group # for selection. if differs: # Generate a string representation of the tags and use # it as index for a project classification. taglist = list(tags) taglist.sort(key=lambda x: x.id) name = ", ".join([t.name for t in taglist]) # Fill data structure for later use available_tag_groups[name] = { 'project_cgroots': projects_cgroots, 'all_cgroots': cg_roots, 'num_differing': num_differing, 'meta': meta, } return available_tag_groups
def get_form(self, step=None, data=None, files=None): form = super(ImportingWizard, self).get_form(step, data, files) current_step = step or self.steps.current if current_step == 'pathsettings': pass # Pre-populate base URL field with settings variable, if available if hasattr(settings, base_url_setting): form.fields['base_url'].initial = getattr( settings, base_url_setting) elif current_step == 'projectselection': # Make sure there is data available. This is needed to test whether # the classification step should be shown with the help of the # show_classification_suggestions() function. cleaned_path_data = self.get_cleaned_data_for_step('pathsettings') if not cleaned_path_data: return form # Get the cleaned data from first step path = cleaned_path_data['relative_path'] filter_term = cleaned_path_data['filter_term'] only_unknown = cleaned_path_data['only_unknown_projects'] base_url = cleaned_path_data['base_url'] # Get all folders that match the selected criteria data_dir = os.path.join(settings.CATMAID_IMPORT_PATH, path) if data_dir[-1] != os.sep: data_dir = data_dir + os.sep if len(filter_term) == "": filter_term = "*" folders, projects, not_readable = find_project_folders( base_url, data_dir, filter_term, only_unknown) # Sort the folders (wrt. short name) to be better readable folders = sorted(folders, key=lambda folder: folder[1]) # Save these settings in the form form.folders = folders form.not_readable = not_readable self.projects = projects # Update the folder list and select all by default form.fields['projects'].choices = folders form.fields['projects'].initial = [f[0] for f in folders] # Get the available user permissions and update the list user_permissions = get_element_permissions(UserProxy, Project) form.user_permissions = user_permissions user_perm_tuples = get_element_permission_tuples(user_permissions) form.fields['user_permissions'].choices = user_perm_tuples # Get the available group permissions and update the list group_permissions = get_element_permissions(GroupProxy, Project) form.group_permissions = group_permissions group_perm_tuples = get_element_permission_tuples( group_permissions) form.fields['group_permissions'].choices = group_perm_tuples elif current_step == 'classification': # Get tag set and all projects within it tags = self.get_cleaned_data_for_step('projectselection')['tags'] tags = frozenset([t.strip() for t in tags.split(',')]) # Get all projects that have all those tags projects = Project.objects.filter(tags__name__in=tags).annotate( repeat_count=Count("id")).filter(repeat_count=len(tags)) # Get all classification graphs linked to those projects and add # them to a form for being selected. workspace = settings.ONTOLOGY_DUMMY_PROJECT_ID croots = {} for p in projects: links_qs = get_classification_links_qs(workspace, p.id) linked_croots = set( [cici.class_instance_b for cici in links_qs]) # Build up dictionary with all classifications mapping to their # linked projects. for cr in linked_croots: try: croots[cr].append(p) except KeyError: croots[cr] = [] croots[cr].append(p) # Remember graphs and projects form.cls_tags = tags form.cls_graph_map = croots self.id_to_cls_graph = {} # Create data structure for form field and id mapping cgraphs = [] for cr in croots: # Create form field tuples name = "%s (%s)" % (cr.name, cr.id) cgraphs.append((cr.id, name)) # Create ID to classification graph mapping self.id_to_cls_graph[cr.id] = cr form.fields['classification_graph_suggestions'].choices = cgraphs #form.fields['classification_graph_suggestions'].initial = [cg[0] for cg in cgraphs] return form
def generate_tag_groups(add_supersets=True, respect_superset_graphs=False): """ This creates a tag sets dictionary. It ignores projects without any tags. """ project_ids, tag_sets, tag_supersets = get_tag_sets(add_supersets) # Get a query set that retrieves all CiCi links for all project ids at once workspace = settings.ONTOLOGY_DUMMY_PROJECT_ID # We are retrieving the classification links of *all* projects. The query # will therefore be much faster, if we get the inverse set of the empty # set instead of explicitely requesting the project_ids to be in # project_ids.. links_qs = get_classification_links_qs(workspace, [], inverse=True) # Make sure the the project ids and the classification root ids are # prefetched links_qs = links_qs.select_related('class_instance_a__project__id', 'class_instance_b__id') # Execute the query set to build a look up table projects_to_cls_links = {} for cici in links_qs: cls_links = projects_to_cls_links.get(cici.class_instance_a.project.id) if not cls_links: cls_links = set() projects_to_cls_links[cici.class_instance_a.project.id] = cls_links cls_links.add(cici.class_instance_b.id) # Test which groups of projects belonging to a particular tag group, # have non-uniform classification graph links # TODO: Test for independent *and* dependent workspace available_tag_groups = {} for tags, projects in tag_sets.items(): differs = False cg_roots = set() projects_cgroots = {} # Collect all classification roots in this tag group for pid in projects: try: # Get set of CiCi links for current project ID croots = projects_to_cls_links[pid] except KeyError: # Use an empty set if there are no CiCi links for the # current project. croots = set() # Remember roots for this projects projects_cgroots[pid] = { 'linked': croots, 'missing': [], 'workspace': workspace, } # Add classification graphs introduced by supersets to the expected # graphs in this tag set. if pid not in tag_supersets[tags] or respect_superset_graphs: cg_roots.update(croots) # Check if there are updates needed for some projects num_differing = 0 meta = [] for pid in projects_cgroots: croots = projects_cgroots[pid]['linked'] diff = cg_roots - croots if len(diff) > 0: differs = True projects_cgroots[pid]['missing'] = diff num_differing = num_differing + 1 strdiff = ", ".join([str(cg) for cg in diff]) meta.append("[PID: %s Missing: %s]" % (pid, strdiff)) # If there is a difference, offer this tag group # for selection. if differs: # Generate a string representation of the tags and use # it as index for a project classification. taglist = list(tags) taglist.sort() name = ", ".join([t for t in taglist]) # Fill data structure for later use available_tag_groups[name] = { 'project_cgroots': projects_cgroots, 'all_cgroots': cg_roots, 'num_differing': num_differing, 'meta': meta, } return available_tag_groups
def get_form(self, step=None, data=None, files=None): form = super(ImportingWizard, self).get_form(step, data, files) current_step = step or self.steps.current if current_step == 'pathsettings': pass # Pre-populate base URL field with settings variable, if available if hasattr(settings, base_url_setting): form.fields['base_url'].initial = getattr(settings, base_url_setting) elif current_step == 'projectselection': # Make sure there is data available. This is needed to test whether # the classification step should be shown with the help of the # show_classification_suggestions() function. cleaned_path_data = self.get_cleaned_data_for_step('pathsettings') if not cleaned_path_data: return form # Get the cleaned data from first step path = cleaned_path_data['relative_path'] filter_term = cleaned_path_data['filter_term'] only_unknown = cleaned_path_data['only_unknown_projects'] base_url = cleaned_path_data['base_url'] # Get all folders that match the selected criteria data_dir = os.path.join(settings.CATMAID_IMPORT_PATH, path) if data_dir[-1] != os.sep: data_dir = data_dir + os.sep if len(filter_term) == "": filter_term = "*" folders, projects, not_readable = find_project_folders( base_url, data_dir, filter_term, only_unknown) # Sort the folders (wrt. short name) to be better readable folders = sorted(folders, key=lambda folder: folder[1]) # Save these settings in the form form.folders = folders form.not_readable = not_readable self.projects = projects # Update the folder list and select all by default form.fields['projects'].choices = folders form.fields['projects'].initial = [f[0] for f in folders] # Get the available user permissions and update the list user_permissions = get_element_permissions(UserProxy, Project) form.user_permissions = user_permissions user_perm_tuples = get_element_permission_tuples(user_permissions) form.fields['user_permissions'].choices = user_perm_tuples # Get the available group permissions and update the list group_permissions = get_element_permissions(GroupProxy, Project) form.group_permissions = group_permissions group_perm_tuples = get_element_permission_tuples(group_permissions) form.fields['group_permissions'].choices = group_perm_tuples elif current_step == 'classification': # Get tag set and all projects within it tags = self.get_cleaned_data_for_step('projectselection')['tags'] tags = frozenset([t.strip() for t in tags.split(',')]) # Get all projects that have all those tags projects = Project.objects.filter( tags__name__in=tags ).annotate( repeat_count=Count("id") ).filter( repeat_count=len(tags) ) # Get all classification graphs linked to those projects and add # them to a form for being selected. workspace = settings.ONTOLOGY_DUMMY_PROJECT_ID croots = {} for p in projects: links_qs = get_classification_links_qs(workspace, p.id) linked_croots = set([cici.class_instance_b for cici in links_qs]) # Build up dictionary with all classifications mapping to their # linked projects. for cr in linked_croots: try: croots[cr].append(p) except KeyError: croots[cr] = [] croots[cr].append(p) # Remember graphs and projects form.cls_tags = tags form.cls_graph_map = croots self.id_to_cls_graph = {} # Create data structure for form field and id mapping cgraphs = [] for cr in croots: # Create form field tuples name = "%s (%s)" % (cr.name, cr.id) cgraphs.append( (cr.id, name) ) # Create ID to classification graph mapping self.id_to_cls_graph[cr.id] = cr form.fields['classification_graph_suggestions'].choices = cgraphs #form.fields['classification_graph_suggestions'].initial = [cg[0] for cg in cgraphs] return form