コード例 #1
0
 class Meta:
     model = Donor
     fields = [
         'name', 't1_codes', 't3_codes', 'new_t1_codes', 'new_t3_codes'
     ]
     widgets = {
         't1_codes':
         selectable.AutoComboboxSelectMultipleWidget(
             lookup_class=T1DonorCodeLookup, ),
         't3_codes':
         selectable.AutoComboboxSelectMultipleWidget(
             lookup_class=T3DonorCodeLookup, ),
     }
コード例 #2
0
ファイル: updateForms.py プロジェクト: udp/rotmic
    def __init__(self, *arg, **kwarg):
        self.request = kwarg.pop('request')
        self.model = kwarg.pop('model', None)

        self.model_admin = admin.site._registry[self.model]
        self.model_form = self.model_admin.get_form(self.request)

        super(UpdateManyForm, self).__init__(*arg, **kwarg)

        f = self.fields['entries']
        lookup = self.lookups.get(self.model, None) \
            or getattr(self.model_admin, 'model_lookup', None)

        f.queryset = self.model.objects.all()
        f.widget = sforms.AutoComboboxSelectMultipleWidget(lookup_class=lookup)
        f.label = self.model._meta.verbose_name + 's'

        self.build_fields()

        if self.request.method == 'GET':
            entries = self.model.objects.select_related().filter(
                pk__in=self.initial['entries'])
            self.populate_fields(entries)

        if self.request.method == 'POST':
            entries = f.widget.value_from_datadict(self.data, self.files,
                                                   'entries')
            entries = self.model.objects.filter(pk__in=entries)
            self.populate_fields(entries)
コード例 #3
0
class GenbankProteinUploadForm(GenbankUploadForm):

    constructs = forms.ModelMultipleChoiceField(
        M.ProteinComponent.objects.all(),
        cache_choices=False,
        required=True,
        widget=sforms.AutoComboboxSelectMultipleWidget(
            lookup_class=L.ProteinLookup),
        label='Protein constructs',
        initial=None,
        help_text='\nStart typing construct ID or name to restrict the choice')
コード例 #4
0
class TracesUploadForm(UploadFormBase):
    """Form for attaching multiple sequencing trace files to selected DNA samples"""

    MATCHCHOICES = (('s', 'sample ID (e.g. A01_comment.ab1)'),
                    ('s.dna', 'construct ID (e.g. rg0011_comment.ab1)'),
                    ('s.container:s',
                     'container + sample ID (e.g. Dna20_A01_comment.ab1)'),
                    ('s:s.dna',
                     'sample ID + construct ID (e.g. A01_rg0011_comment.ab1)'))

    samples = forms.ModelMultipleChoiceField(
        M.DnaSample.objects.all(),
        cache_choices=False,
        required=True,
        widget=sforms.AutoComboboxSelectMultipleWidget(
            lookup_class=L.DnaSampleLookup),
        label='Samples',
        initial=None,
        help_text=
        'Start typing container, sample or construct ID to restrict the choice.'
    )

    matchBy = forms.ChoiceField(
        label='match by',
        choices=MATCHCHOICES,
        initial='s',
        widget=forms.RadioSelect,
        required=True,
        help_text="""Select how trace file names are matched to samples.
File names need to contain certain characters that separate the different IDs 
from each other and from the rest of the name. Allowed separating characters 
are: 

'_'(underscore), ' '(space), ':'(colon), ';'(semicolon), '-'(minus).

IDs are converted to lower case and leading zeros are removed to make the 
matching more robust. For example, let's assume you have a sample with ID 
'A01' which contains the DNA construct with ID 'sb0001'. If you select sample 
ID + construct ID matching, the following file names are all correct and will 
match the trace to this sample:

A1_sb0001_mysequencing.ab1 or 
a1-sb1-mysequencing.ab1 or 
A01:sb001_mysequencing.ab1
""")

    matchPrimer = forms.BooleanField(
        required=True,
        label='extract primer ID',
        initial=True,
        help_text="""Try to find a sequencing primer ID within the file name.
The trace file name may contain the ID of a sequencing primer. This ID has to
be an exact match (including capitalization/case and leading zeros) with the 
primer ID. The primer name does <em>not</em> work. The import will proceed 
even if there is no match, in which case the primer field is left empty for 
this trace.
""")

    files = MultiFileField(
        label='Trace files:',
        min_num=2,
        extensions=['ab', 'abi', 'ab1', 'scf', 'phd'],
        help_text=
        'hold <CTRL> to select multiple files. Expected formats are: *.ab, *.abi, *.ab1,*.scf, *.phd'
    )

    evaluation = forms.ChoiceField(
        label='evaluation',
        choices=M.Sequencing.EVALUATIONS,
        initial='none',
        required=True,
        help_text='pre-set sequencing verdict with respect to target')

    orderedAt = forms.DateField(initial=datetime.now().date,
                                label="ordered",
                                widget=AdminDateWidget)

    orderedBy = forms.ModelChoiceField(
        User.objects.all(),
        required=True,
        label='By',
        widget=sforms.AutoComboboxSelectWidget(lookup_class=L.UserLookup,
                                               allow_new=False,
                                               attrs={'size': 15}),
        help_text=
        'User responsible for this sequencing\nStart typing user name to restrict choices.'
    )

    comments = forms.CharField(
        label='Comments',
        required=False,
        widget=forms.Textarea(attrs={
            'rows': 4,
            'cols': 80
        }),
        help_text=
        'This same comment will be put into every new sequencing record')

    def __init__(self, *arg, **kwarg):
        super(TracesUploadForm, self).__init__(*arg, **kwarg)

        ## Note: the 'self.fields['orderedBy'].initial =' syntax doesn't work with selectable fields
        self.initial['orderedBy'] = str(self.request.user.id)

    def _matchitems(self, fields, sample):
        """
        Extract displayIds from sample or sample sub-fields specified in fields.
        Normalize each ID to lower case and remove any leading zeros
        @return [str] - list of one or two IDs 
        """
        s = sample  ## fields are supposed to be 's' or 's.container' etc.
        r = [eval(f + '.displayId') for f in fields]
        r = [self.normalize(s) for s in r]
        return tuple(r)

    def clean_samples(self):
        """
        Ensure unique sample IDs needed for file name matching
        Convert sample list into a dict indexed by the ID or IDs used for matching.
        """
        data = self.cleaned_data['samples']
        fields = self.data['matchBy'].split(':')

        sdic = {self._matchitems(fields, s): s for s in data}

        ## verify that all sample ids are unique with the current match
        if len(sdic) < len(data):
            raise forms.ValidationError(\
                'Sorry, there are samples with identical IDs in the selected set. '+\
                'Select fewer samples or change the file name matching below.',
            code='invalid')

        return sdic

    def _findsample(self, fname, sdic):
        n_fields = len(
            sdic.keys()[0])  ## how many fragments are supposed to match?

        sep = self.ID_SEPARATORS
        frags = [self.normalize(x) for x in re.split(sep, fname)]

        searchfrags = tuple(
            frags[:n_fields])  ## should be first 1 or 2 fragments
        if searchfrags in sdic:
            return sdic[searchfrags]

        self.add_error('files',\
            'Cannot match %s to any of the samples.' % fname +\
            'No sample can be identified by %s.' % ' + '.join(searchfrags) )
        return None

    def findprimer(self, fname, primers=[]):
        """try identifying a sequencing primer ID in the filename"""
        for p in primers:
            if p.displayId in fname:
                return p
        return None

    def mapTracesToSamples(self, files):
        """map given InMemoryFileUpload files to samples by name"""
        sdic = self.cleaned_data['samples']

        r = {s: [] for s in sdic.values()}

        for f in files:
            s = self._findsample(f.name, sdic)
            if s:
                r[s] += [f]

        if [] in r.values():
            missing = [str(s) for s in r.keys() if r[s] == []]
            self.add_error('files',
                           'Could not find traces for the following samples: '+\
                           ', '.join(missing))

        return r

    def createSeq(self, sample, traces, **kwargs):
        """Create and save new sequencing and sequencingRun instances"""

        for key in ['orderedBy', 'orderedAt', 'evaluation', 'comments']:
            kwargs[key] = self.cleaned_data[key]

        kwargs['registeredBy'] = self.request.user
        kwargs['registeredAt'] = datetime.now()

        kwargs['comments'] += '\n(Created through trace file upload)'

        r = M.Sequencing(sample=sample, **kwargs)
        r.save()

        seqprimers = M.OligoComponent.objects.filter(
            componentType=T.ocSequencing)

        for f in traces:

            if self.cleaned_data['matchPrimer']:
                primer = self.findprimer(f.name, seqprimers)

            run = M.SequencingRun(parent=r,
                                  f=f,
                                  description='multiple file upload',
                                  primer=primer)
            run.save()
コード例 #5
0
class GenbankUploadForm(UploadFormBase):

    constructs = forms.ModelMultipleChoiceField(
        M.DnaComponent.objects.all(),
        cache_choices=False,
        required=True,
        widget=sforms.AutoComboboxSelectMultipleWidget(
            lookup_class=L.DnaLookup),
        label='DNA constructs',
        initial=None,
        help_text='\nStart typing construct ID or name to restrict the choice')

    genbank = MultiFileField(label='Genbank file(s)',
                             min_num=1,
                             extensions=['gb', 'gbk', 'genbank'],
                             help_text="""Hold <CTRL> to select multiple files.
The genbank record name (LOCUS) will be used to match the record to a construct. 
This record name must start with the construct's rotmic ID (lower or upper case, 
leading zeros can vary). The ID should be separated from the rest of the name 
(if any) with one or several ' '(space), '-', '_', ':', or ';'.

Example:
   LOCUS SB020_testconstruct ...
   
   will be matched to a construct with ID sb0020.
""")

    def clean_constructs(self):
        """
        Convert dna list into a dict indexed by the ID for matching.
        """
        data = self.cleaned_data['constructs']

        sdic = {self.normalize(s.displayId): s for s in data}

        ## verify that all construct ids are unique with the current match
        if len(sdic) < len(data):
            raise forms.ValidationError(\
                'Sorry, there are constructs with (almost) identical IDs in the selected set. '+\
                'For example: SB0001 would be considered the same as sb01',
            code='invalid')

        return sdic

    def clean_genbank(self):
        """Convert uploaded file(s) into list of genbank record objects"""
        data = self.cleaned_data['genbank']

        r = []
        concat = ''
        try:
            ## BioPython genbank writing is sensitive to all kind of errors
            ## we therefore first concatenate all genbank files into one big string
            ## then parse it record by record which allows us to store
            ## the **original** genbank string along with the Biopython object
            for f in data:
                concat += ''.join(f.readlines()).strip()

            if concat:

                records = concat.split(
                    '//')[:-1]  ## skip '' split fragment after last //
                records = [s + '//' for s in records]

                for i, s in enumerate(records):
                    f = StringIO.StringIO(s)
                    seqrecord = SeqIO.parse(f, 'gb').next()

                    seqrecord.original = s
                    r += [seqrecord]

        except StopIteration, why:
            raise forms.ValidationError('Empty or corrupted genbank record #%i: %s' % \
                                        (i+1, why))
        except ValueError, why:
            raise forms.ValidationError('Error parsing genbank record #%i: %s' % \
                                        (i+1, why))