Example #1
0
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
Example #2
0
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
Example #3
0
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
Example #4
0
    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
Example #5
0
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
Example #6
0
    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