Ejemplo n.º 1
0
    def changeUnit(self, unit):

        posDisp = self.numDims * [None]
        for i in range(self.numDims):
            posDisp[i] = float(self.dimensionEntries[i].get())
            if self.unit != 'point':
                dataDim = self.dataDims[i]
                if dataDim.className == 'FreqDataDim':
                    posDisp[i] = unit_converter[(self.unit, 'point')](
                        posDisp[i], getPrimaryDataDimRef(dataDim))

        self.unit = unit
        if self.unit != 'point':
            for i in range(self.numDims):
                dataDim = self.dataDims[i]
                if dataDim.className == 'FreqDataDim':
                    posDisp[i] = unit_converter[('point', self.unit)](
                        posDisp[i], getPrimaryDataDimRef(dataDim))

        for i in range(self.numDims):
            value = posDisp[i]
            if value is None:
                self.dimensionEntries[i].set('None')
            else:
                self.dimensionEntries[i].set('%8.4f' % posDisp[i])
Ejemplo n.º 2
0
def getPeakListParams( params ):
  """ Get all the parameters needed from the peak list """

  if not params.peakList:
    return

  # These are just handy
  peakList          = params.peakList
  dataSource        = peakList.getDataSource()
  analysisSpectrum  = dataSource.analysisSpectrum
  analysisProject   = analysisSpectrum.analysisProject

  # Now setting parameters (from Peak List)
  params.dataDimRefs = []
  params.isFreqDim   = []

  params.Ndim       = dataSource.numDim                           # set Ndim
  params.dataFile   = dataSource.dataStore.fullPath               # set dataFile

  for i, dataDim in enumerate( dataSource.sortedDataDims() ):

    if isinstance( dataDim, FreqDataDim ):
      dataDimRef = getPrimaryDataDimRef( dataDim )
      params.dataDimRefs.append( dataDimRef )                     # set dataDimRefs
      params.isFreqDim.append( True )                             # set isFreqDim
    else:
      params.dataDimRefs.append( None )                           # set dataDimRefs
      params.isFreqDim.append( False )                            # set isFreqDim

  params.minHeight        = min(analysisSpectrum.posLevels) * analysisProject.getGlobalContourScale()
                                                                  # set minHeight
  params.nPoints          = list(dataSource.dataStore.numPoints)  # set nPoints
  params.blockSize        = list(dataSource.dataStore.blockSizes) # set blockSize
  params.dimWrapped       = [0] * params.Ndim                     # ask wayne about this one...
  params.isBigEndian      =  1 if dataSource.dataStore.isBigEndian else 0
Ejemplo n.º 3
0
    def commit(self):

        posDisp = self.numDims * [0]

        for i in range(self.numDims):
            posDisp[i] = float(self.dimensionEntries[i].get())
            if self.unit != 'point':
                dataDim = self.dataDims[i]
                if dataDim.className == 'FreqDataDim':
                    self.posn[i] = unit_converter[(self.unit, 'point')](
                        posDisp[i], getPrimaryDataDimRef(dataDim))

            else:
                self.posn[i] = posDisp[i]

        if self.peak:
            movePeak(self.peak, self.posn)
        else:
            self.peak = pickPeak(self.peakList, self.posn)

        height = self.heightEntry.get()
        volume = self.volumeEntry.get()
        setManualPeakIntensity(self.peak, height, intensityType='height')
        setManualPeakIntensity(self.peak, volume, intensityType='volume')

        details = self.detailEntry.get() or None

        self.peak.setDetails(details)

        self.close()
Ejemplo n.º 4
0
    def dataDimText(self, dataDim):

        dataDimRef = getPrimaryDataDimRef(dataDim)

        if dataDimRef:
            isotope = '/'.join(dataDimRef.expDimRef.isotopeCodes)
        else:
            isotope = 'None'

        text = str(dataDim.dim) + ' (%s)' % isotope

        return text
Ejemplo n.º 5
0
    def updateDataDimList(self, *extra):

        textMatrix = []
        self.dataDims = []
        isotopeCodes = getPrimaryDataDimRef(
            self.dataDim).expDimRef.isotopeCodes
        project = self.dataDim.root
        for experiment in self.nmrProject.experiments:
            for spectrum in experiment.dataSources:
                if (isSpectrum(spectrum)):
                    for dataDim in spectrum.sortedDataDims():
                        if (isinstance(dataDim, Nmr.FreqDataDim)):
                            expDimRef = getPrimaryDataDimRef(dataDim).expDimRef
                            if (expDimRef.isotopeCodes == isotopeCodes):
                                if (not hasattr(dataDim, 'change_ref')):
                                    if (dataDim == self.dataDim):
                                        dataDim.change_ref = True
                                    else:
                                        dataDim.change_ref = False
                                text = []
                                text.append(experiment.name)
                                text.append(spectrum.name)
                                text.append(self.dataDimText(dataDim))
                                dataDimRef = getPrimaryDataDimRef(dataDim)
                                text.append(
                                    formatFloat(dataDimRef.refPoint, places=6))
                                text.append(
                                    formatFloat(dataDimRef.refValue, places=6))
                                if (dataDim.change_ref):
                                    text.append(yes_string)
                                else:
                                    text.append(no_string)
                                textMatrix.append(text)
                                self.dataDims.append(dataDim)

        self.datadim_list.update(objectList=self.dataDims,
                                 textMatrix=textMatrix)
Ejemplo n.º 6
0
    def apply(self):

        refppm = self.refppm_entry.get()

        if (refppm is None):
            showError('No reference',
                      'Must specify reference ppm.',
                      parent=self)
            return False

        delta_refppm = refppm - self.current_refppm

        for dataDim in self.dataDims:
            if (dataDim.change_ref):
                dataDimRef = getPrimaryDataDimRef(dataDim)
                dataDimRef.refValue = dataDimRef.refValue + delta_refppm
            del dataDim.change_ref

        return True
Ejemplo n.º 7
0
def setupPeaks(peakList, data):

    # below assumes that all positions found are in ppm and in fundamental region
    spectrum = peakList.parent
    numDim = spectrum.numDim
    dataDims = spectrum.sortedDataDims()
    dataDimRefs = [getPrimaryDataDimRef(dataDim) for dataDim in dataDims]
    for (position, height, volume, quality) in data:
        peak = peakList.newPeak()
        peakDims = peak.sortedPeakDims()
        for i in range(numDim):
            peakDim = peakDims[i]
            dataDimRef = dataDimRefs[i]
            peakDim.dataDimRef = dataDimRef
            #peakDim.position = dataDimRef.valueToPoint(position[i])
            peakDim.value = position[i]
        setManualPeakIntensity(peak, height, 'height')
        setManualPeakIntensity(peak, volume, 'volume')
        if quality >= 0:  # = -1 if not calculated
            peak.figOfMerit = quality  # assumes that quality is between and 0 and 1
Ejemplo n.º 8
0
def pickAssignSpecFromRoot(argServer, rootPeakList=None, targetPeakList=None):

    toleranceDict = {'1H': 0.03, '13C': 0.1, '15N': 0.15}

    assert argServer or (rootPeakList and targetPeakList)

    if argServer:
        project = argServer.getProject()
    else:
        project = rootPeakList.root

    spectra = []
    for experiment in project.currentNmrProject.sortedExperiments():
        for spectrum in experiment.sortedDataSources():
            spectra.append(spectrum)

    if not rootPeakList:
        rootSpec = argServer.getSpectrum(spectra)
        rootPeakList = argServer.getPeakList(rootSpec)

    rootSpec = rootPeakList.dataSource
    rootIsotopes = getSpectrumIsotopes(rootSpec)

    tolerances = []
    for isotope in rootIsotopes:
        tolerance = argServer.askFloat(
            '%s tolerance' % isotope, toleranceDict.get(
                isotope, 0.1)) or toleranceDict.get(isotope, 0.1)
        tolerances.append(tolerance)

    if not targetPeakList:
        targetSpectra = []
        for experiment in project.currentNmrProject.experiments:
            for spectrum in experiment.dataSources:
                isotopes = getSpectrumIsotopes(spectrum)
                n = 0
                for isotope in rootIsotopes:
                    if isotope in isotopes:
                        isotopes.remove(isotope)
                        n += 1

                if n == len(rootIsotopes):
                    targetSpectra.append(spectrum)

        targetSpec = argServer.getSpectrum(targetSpectra)
        targetPeakList = argServer.getPeakList(targetSpec)

    targetSpec = targetPeakList.dataSource

    if not targetSpec:
        argServer.showWarning('No suitable target spectra found.')

    # Determine mapping of root to target dimensions according to data dim isotopes.
    #  - Only ask user if there are multiple possibilities.

    mapping = []
    targetIsotopes = getSpectrumIsotopes(targetSpec)
    i = 0

    for isotope in rootIsotopes:
        if targetIsotopes.count(isotope) == 1:
            mapping.append(targetIsotopes.index(isotope))

        else:
            j = 0
            matches = []
            for targetIsotope in targetIsotopes:
                if targetIsotope == isotope:
                    matches.append(j)
                j += 1

            for j in matches[:-1]:
                if argServer.askYesNo(
                        'Match root dimension %d (%s) to target dimension %d?'
                        % (i + 1, isotope, j + 1)):
                    mapping.append(j)
                    break

            else:
                mapping.append(matches[-1])

        i += 1

    fullRegion = []
    for dataDim in targetSpec.sortedDataDims():

        if dataDim.className == 'FreqDataDim':
            dataDimRef = getPrimaryDataDimRef(dataDim)
            valueMax = pnt2ppm(1, dataDimRef)
            valueMin = pnt2ppm(dataDim.numPoints, dataDimRef)
            fullRegion.append([valueMin, valueMax])
        else:
            fullRegion.append([1, dataDim.numPoints])

    M = len(rootPeakList.peaks)
    c = 0

    foundPeaks = 0
    for peak in rootPeakList.peaks:

        region = list(fullRegion)

        for i, peakDim in enumerate(peak.sortedPeakDims()):
            if peakDim.dataDimRef:
                error = tolerances[i]
                value = peakDim.value
                region[mapping[i]] = (value - error, value + error)

        peaks = searchPeaks([
            targetPeakList,
        ], region)
        peaks.extend(findPeaks(targetPeakList, region))

        # possible to grow the region here of no peaks are found

        for peak2 in peaks:
            for intens in peak.peakIntensities:
                if str(intens.value) == 'inf':
                    peaks.remove(peak2)
                    peak2.delete()
                    break

        foundPeaks += len(peaks)
        c += 1

        for i, peakDim in enumerate(peak.sortedPeakDims()):
            for peak2 in peaks:
                peakDim2 = peak2.sortedPeakDims()[mapping[i]]
                if len(peakDim2.peakDimContribs) < 1:
                    for contrib in peakDim.peakDimContribs:
                        assignResToDim(peakDim2,
                                       contrib.resonance,
                                       doWarning=0)

        print 'Root peak %d of %d' % (c, M)

    if argServer:
        name = '%s:%s' % (targetPeakList.dataSource.experiment.name,
                          targetPeakList.dataSource.name)
        argServer.showInfo('Picked %d peaks in %s' % (foundPeaks, name))

    return targetPeakList.peaks
Ejemplo n.º 9
0
    def update(self, peak=None, peakList=None):

        # first destroy old labels and entries (saves grid hassles)

        for label in self.dimensionLabels:
            label.destroy()
        for entry in self.dimensionEntries:
            entry.destroy()

        # now setup required data

        if peak:
            title = 'Edit Peak'
            self.buttons.buttons[0].config(text='Update')
        else:
            title = 'Add Peak'
            self.buttons.buttons[0].config(text='Add Peak')

        self.setTitle(title)

        self.peak = peak
        self.peakList = peakList
        if not peakList:
            if peak:
                self.peakList = peak.peakList
            else:
                return

        peakList = self.peakList
        spectrum = peakList.dataSource.name
        self.numDims = peakList.dataSource.numDim
        self.posn = self.numDims * [0]
        self.dataDims = peakList.dataSource.sortedDataDims()

        if self.peak:

            serial = self.peak.serial
            dims = self.peak.sortedPeakDims()
            details = self.peak.details
            if not details:
                details = ''
            if self.peak.annotation:
                annotn = '%0.16s' % self.peak.annotation
            else:
                annotn = ''

            heightIntensity = self.peak.findFirstPeakIntensity(
                intensityType='height')
            volumeIntensity = self.peak.findFirstPeakIntensity(
                intensityType='volume')

            if heightIntensity:
                height = heightIntensity.value
            else:
                height = 0.0

            if volumeIntensity:
                volume = volumeIntensity.value
            else:
                volume = 0.0

            for i in range(self.numDims):
                peakDim = dims[i]
                dataDimRef = peakDim.dataDimRef
                if dataDimRef:
                    self.posn[i] = peakDim.position + (
                        peakDim.numAliasing * dataDimRef.dataDim.numPointsOrig)
                else:
                    self.posn[i] = peakDim.position

        else:

            dict = peakList.__dict__.get('serialDict')
            if dict is None:
                serial = 1
            else:
                serial = dict.get('peaks', 0) + 1

            height = 0.0
            volume = 0.0
            details = ''
            annotn = ''

        self.specLabel.set(
            text='Experiment: %s Spectrum: %s PeakList: %d' %
            (peakList.dataSource.experiment.name, spectrum, peakList.serial))
        self.peakLabel.set(text='Peak: %d' % serial)

        self.dimensionLabels = self.numDims * ['']
        self.dimensionEntries = self.numDims * ['']
        for i in range(self.numDims):
            pos = self.posn[i]
            if self.unit != 'point':
                dataDim = self.dataDims[i]
                if dataDim.className == 'FreqDataDim':
                    pos = unit_converter[('point', self.unit)](
                        pos, getPrimaryDataDimRef(dataDim))
            self.dimensionLabels[i] = Label(self.master_frame,
                                            text='F%d' % (i + 1),
                                            borderwidth=2,
                                            relief='groove')
            tipText = 'The peak position in dimension %d, in the specified units' % (
                i + 1)
            self.dimensionEntries[i] = FloatEntry(self.master_frame,
                                                  borderwidth=1,
                                                  text='%8.4f' % pos,
                                                  tipText=tipText)

        self.heightEntry.set(text='%f' % height)
        self.volumeEntry.set(text='%f' % volume)
        self.detailEntry.set(text=details)

        row = 0
        self.specLabel.grid(row=row, column=0, columnspan=2, sticky='nsew')

        row = row + 1
        self.peakLabel.grid(row=row, column=0, sticky='nsew')
        self.unit_frame.grid(row=row, column=1, columnspan=2, sticky='nsew')

        for i in range(self.numDims):
            row = row + 1
            self.dimensionLabels[i].grid(row=row, column=0, sticky='nsew')
            self.dimensionEntries[i].grid(row=row,
                                          column=1,
                                          columnspan=3,
                                          sticky='e')

        row = row + 1
        self.heightLabel.grid(row=row, column=0, sticky='nsew')
        self.heightEntry.grid(row=row, column=1, columnspan=3, sticky='e')

        row = row + 1
        self.volumeLabel.grid(row=row, column=0, sticky='nsew')
        self.volumeEntry.grid(row=row, column=1, columnspan=3, sticky='e')

        row = row + 1
        self.detailLabel.grid(row=row, column=0, sticky='nsew')
        self.detailEntry.grid(row=row, column=1, columnspan=3, sticky='e')

        row = row + 1
        self.buttons.grid(row=row, column=0, columnspan=4, sticky='nsew')
Ejemplo n.º 10
0
    def body(self, guiFrame):

        dataDim = self.dataDim
        dataDimRef = getPrimaryDataDimRef(dataDim)
        spectrum = dataDim.dataSource

        guiFrame.grid_columnconfigure(0, weight=1)

        row = 0
        label = Label(guiFrame, text='Experiment:', grid=(row, 0), sticky='e')
        tipText = 'The name of the experiment that contains the spectrum to be re-referenced'
        label = Label(guiFrame,
                      text=spectrum.experiment.name,
                      grid=(row, 1),
                      tipText=tipText)

        row += 1
        label = Label(guiFrame, text='Spectrum:', grid=(row, 0), sticky='e')
        tipText = 'The name of the spectrum to be re-referenced'
        label = Label(guiFrame,
                      text=spectrum.name,
                      grid=(row, 1),
                      tipText=tipText)

        row += 1
        label = Label(guiFrame, text='Dimension:', grid=(row, 0), sticky='e')
        tipText = 'The number of the spectrum dimension that will be re-referenced'
        label = Label(guiFrame,
                      text=self.dataDimText(dataDim),
                      grid=(row, 1),
                      tipText=tipText)

        row += 1
        label = Label(guiFrame,
                      text='Chosen reference point:',
                      grid=(row, 0),
                      sticky='e')
        text = formatFloat(self.position, places=6)
        tipText = 'The chosen position in the spectrum dimension (where the mouse was clicked) in data matrix points'
        label = Label(guiFrame, text=text, grid=(row, 1), tipText=tipText)

        row += 1
        label = Label(guiFrame,
                      text='Current reference ppm at this point:',
                      grid=(row, 0),
                      sticky='e')
        self.current_refppm = convertPosition(self.position,
                                              dataDimRef,
                                              toUnit='ppm')
        text = formatFloat(self.current_refppm, places=6)
        tipText = 'The ppm value currently associated with this points location'
        label = Label(guiFrame, text=text, grid=(row, 1), tipText=tipText)

        row += 1
        label = Label(guiFrame,
                      text='New reference ppm at this point:',
                      grid=(row, 0),
                      sticky='e')
        tipText = 'Inputs a new value for the exact ppm position of the selected point; consequently re-referencing the spectrum dimension'
        self.refppm_entry = FloatEntry(guiFrame,
                                       width=30,
                                       grid=(row, 1),
                                       sticky='ew',
                                       tipText=tipText)
        self.refppm_entry.set(0.0)  # default

        row += 1
        guiFrame.grid_rowconfigure(row, weight=1)
        tipTexts = [
            'The name of experiments within the project containing similar spectrum dimensions',
            'The name of the spectrum within the project that may be re-referenced',
            'The spectrum dimension to which the re-referencing may apply',
            'The current reference point for the spectrum dimension in its spectrum data matrix',
            'The current reference ppm value for the spectrum dimension; the value at the reference point',
            'Sets whether the spectrum dimension will be re-referenced using the above reference point and ppm value'
        ]
        headings = ('Experiment', 'Spectrum', 'Dimension', 'Reference\npoint',
                    'Reference\nppm', 'Change\nreferencing')
        editWidgets = editSetCallbacks = 6 * [None]
        editGetCallbacks = [None, None, None, None, None, self.toggleChangeRef]
        self.datadim_list = ScrolledMatrix(guiFrame,
                                           headingList=headings,
                                           initialRows=4,
                                           editWidgets=editWidgets,
                                           editGetCallbacks=editGetCallbacks,
                                           editSetCallbacks=editSetCallbacks,
                                           grid=(row, 0),
                                           gridSpan=(1, 2),
                                           tipTexts=tipTexts)
        tipTexts = [
            'Re-reference the selected spectrum dimensions using the stated ppm value',
        ]
        row += 1
        texts = ['Commit']
        commands = [self.ok]
        buttons = UtilityButtonList(guiFrame,
                                    texts=texts,
                                    commands=commands,
                                    doClone=False,
                                    closeText='Cancel',
                                    helpUrl=self.help_url,
                                    grid=(row, 0),
                                    gridSpan=(1, 2),
                                    tipTexts=tipTexts)

        self.updateDataDimList()
Ejemplo n.º 11
0
def linkSpinSystemInterIntraResonances(spinSystem,
                                       activeLists,
                                       tolerances=None):

    nmrProject = spinSystem.topObject
    prevSpinSystem = findConnectedSpinSystem(spinSystem)
    allowedRefExps, coRefExps = getSeqAssignRefExperiments(nmrProject.root)

    if not prevSpinSystem:
        if spinSystem.residue:
            residueB = getLinkedResidue(spinSystem.residue, linkCode='prev')
            prevSpinSystem = nmrProject.findFirstResonanceGroup(
                residue=residueB)

    if not prevSpinSystem:
        prevSpinSystem = nmrProject.newResonanceGroup()
        makeSeqSpinSystemLink(prevSpinSystem, spinSystem)

    peaks = []
    found = {}
    expTypes = {}
    linkDims = {}

    # go though the peaks associated with this spin system
    # within the selected peak lists
    # find the indirect, linking dimension
    for resonance in spinSystem.resonances:
        if resonance.isotopeCode != '15N':
            continue

        if not isResonanceAmide(resonance):
            continue

        for contrib in resonance.peakDimContribs:
            peakDim = contrib.peakDim
            peak = peakDim.peak

            if found.get(peak):
                continue

            peakList = peak.peakList
            if peakList not in activeLists:
                continue

            setupPeakHeight(peak)
            intensity = peak.findFirstPeakIntensity(intensityType='height')
            if not intensity:
                continue

            spectrum = peakList.dataSource
            expType = expTypes.get(peakList, spectrum.experiment.refExperiment)
            expTypes[peakList] = expType

            linkDim = linkDims.get(peakList)
            if linkDim is None:
                boundDict = {}
                for dataDimA, dataDimB in getOnebondDataDims(spectrum):
                    boundDict[dataDimA] = dataDimB
                    boundDict[dataDimB] = dataDimA

                dims = []
                for dataDim in spectrum.dataDims:
                    dataDimRef = getPrimaryDataDimRef(dataDim)

                    if not dataDimRef:
                        continue

                    isotopes = '/'.join(dataDimRef.expDimRef.isotopeCodes)
                    dims.append((isotopes, dataDim))

                dims.sort()
                for isotopes, dataDim in dims:
                    if '13C' == isotopes:
                        linkDim = (dataDim.dim, isotopes)
                        break

                    elif '1H' == isotopes:
                        dataDimB = boundDict.get(dataDim)

                        if dataDimB:
                            dataDimRefB = getPrimaryDataDimRef(dataDimB)

                            if '15N' in dataDimRefB.expDimRef.isotopeCodes:
                                continue

                        linkDim = (dataDim.dim, isotopes)
                        break

                linkDims[peakList] = linkDim

            if linkDim is None:
                continue

            if peakDim.dim is linkDim[0]:
                continue

            found[peak] = True
            peakDimL = peak.findFirstPeakDim(dim=linkDim[0])
            isotope = linkDim[1]

            peaks.append((peak, expType, peakDimL, isotope, intensity.value))

    peakTypes = []
    interResonances = {}
    intraResonances = {}
    for peak, expType, peakDim, isotope, height in peaks:

        ppm = peakDim.value
        atomType = None

        if expType in coRefExps:
            isInter = True
        elif 'N[coca]' in expType.name:
            isInter = False
        elif 'N_' in expType.name:
            isInter = False
        else:
            isInter = None

        resonance = None
        contrib = peakDim.findFirstPeakDimContrib()
        if contrib:
            resonance = contrib.resonance

            if isInter and resonance.assignNames:
                atomType = resonance.assignNames[0]
                interResonances[atomType] = (resonance, ppm, prevSpinSystem)

            if (isInter is False) and resonance.assignNames:
                atomType = resonance.assignNames[0]
                intraResonances[atomType] = (resonance, ppm, spinSystem)

        if not atomType:
            atomType = guessAtomType(expType, ppm, height)

        peakTypes.append((peakDim, atomType, contrib, isotope, isInter, ppm))

    # Get known inter/intra resonance assignments
    # for each atom type
    for peakDim, atomType, contrib, isotope, isInter, ppm in peakTypes:
        if isInter is None:
            continue
        elif isInter:
            resDict = interResonances
            uniqSpinSystem = prevSpinSystem
        else:
            resDict = intraResonances
            uniqSpinSystem = spinSystem

        if atomType:
            resonance, ppm2, ss = resDict.get(atomType, (None, None, None))

            if (resonance is None) and contrib:
                resDict[atomType] = (contrib.resonance, ppm, uniqSpinSystem)

    # Make any new assignments for the unambig peaks
    untypedIntra = []
    untypedInter = []
    for i, data in enumerate(peakTypes):
        (peakDim, atomType, contrib, isotope, isInter, ppm) = data

        if isInter is None:
            continue

        elif isInter:
            untyped = untypedInter
            resDict = interResonances
            uniqSpinSystem = prevSpinSystem

        else:
            resDict = intraResonances
            untyped = untypedIntra
            uniqSpinSystem = spinSystem

        if atomType:
            # Get any previously used resonances for this atom type
            resonance, ppm2, ss = resDict.get(atomType, (None, None, None))

            # If no prev resonance, look at the peak assignment
            if (not resonance) and contrib:
                resonance = contrib.resonance

            # Check to ensure that any existing resonance
            # is from the correct, this/prev spin system
            if resonance:
                spinSystem2 = resonance.resonanceGroup
                if spinSystem2 and (spinSystem2 is not uniqSpinSystem):
                    resonance = None

            # If no valid reasonance yet, check named ones
            # in the required spin system
            if not resonance:
                for resonance2 in uniqSpinSystem.resonances:
                    if atomType in resonance2.assignNames:
                        resonance = resonance2
                        break

            # If no valid resonance yet, make a new one
            if not resonance:
                resonance = nmrProject.newResonance(isotopeCode=isotope)

            # If peak dim is assigned to the wrong resonance
            # clear the assignment
            if contrib and contrib.resonance is not resonance:
                clearPeakDim(peakDim)
                contrib = None

            # Ensure the peak dim is assigned correctly
            if not contrib:
                assignResToDim(peakDim, resonance)

            # Check type of resonance set correctly
            if not resonance.assignNames:
                assignResonanceType(resonance, assignNames=(atomType, ))

            # Check spin system set correctly
            if resonance.resonanceGroup is not uniqSpinSystem:
                addSpinSystemResonance(uniqSpinSystem, resonance)

            # Store resonance by atom type, so that it can
            # be picked up later
            resDict[atomType] = (resonance, ppm, uniqSpinSystem)

        else:
            untyped.append((peakDim, contrib, isotope, isInter, ppm, i))

    uniqResonances = interResonances.values() + intraResonances.values()

    # Cluster untyped peaks
    interCluster = {}
    intraCluster = ()

    interData = (untypedInter, interCluster, prevSpinSystem)
    intraData = (untypedIntra, intraCluster, spinSystem)

    for untyped, clusters, uniqSpinSystem in (interData, intraData):

        for peakDim, contrib, isotope, isInter, ppm, i in untyped:

            if peakDim in clusters:
                continue

            if tolerances:
                tolerance = tolerances[isotope]
            else:
                tolerance = getAnalysisDataDim(peakDim.dataDim).assignTolerance

            if contrib:
                resonance = contrib.resonance
            else:
                resonance = None

            cluster = [peakDim]
            interCluster[peakDim] = True
            for peakDimB, contribB, isotopeB, isInterB, ppmB, i in untyped:
                if isotope != isotopeB:
                    continue

                if abs(ppmB - ppm) > tolerance:
                    continue

                if peakDim.peak.peakList == peakDimB.peak.peakList:
                    continue

                if contribB:
                    if not resonance:
                        resonance = contribB.resonance
                    if resonance is not contribB.resonance:
                        clearPeakDim(peakDimB)
                        assignResToDim(peakDimB,
                                       resonance,
                                       tolerance=tolerance)

                cluster.append(peakDimB)
                clusters[peakDimB] = True

            if not resonance:
                # Try to macth to any typed peaks
                for peakDimB, atomType, contribB, isotopeB, isInterB, ppmB in peakTypes:
                    if not contribB:
                        continue

                    if not atomType:
                        continue

                    if isotope != isotopeB:
                        continue

                    if abs(ppmB - ppm) > tolerance:
                        continue

                    if peakDim.peak.peakList == peakDimB.peak.peakList:
                        continue

                    resonance = contribB.resonance

                    # Set type for this peak
                    peakTypes[i] = (peakDim, atomType, contrib, isotope,
                                    isInter, ppm)
                    break

            if not resonance:
                resonance = nmrProject.newResonance(isotopeCode=isotope)

            for peakDimC in cluster:
                clearPeakDim(peakDimC)
                assignResToDim(peakDimC, resonance, tolerance=tolerance)

            uniqResonances.append((resonance, ppm, uniqSpinSystem))

            if resonance.resonanceGroup is not uniqSpinSystem:
                addSpinSystemResonance(uniqSpinSystem, resonance)

    # E.g. Find the HNCA peaks which best match the HNcoCA/iHNCA resonances
    matchDict = {}
    closestDict = {}
    for peakDim, atomType, contrib, isotope, isInter, ppm in peakTypes:
        if isInter is not None:
            # Not through HNcoCA or iHNCA
            continue

        if tolerances:
            tolerance = tolerances[isotope]
        else:
            tolerance = getAnalysisDataDim(peakDim.dataDim).assignTolerance

        matches = []
        shiftList = peakDim.peak.peakList.dataSource.experiment.shiftList
        for resonanceB, ppm2, uniqSpinSystem in uniqResonances:

            if resonanceB.isotopeCode != isotope:
                continue

            assignNames = resonanceB.assignNames
            if assignNames and (atomType not in assignNames):
                continue

            if not ppm2:
                shift = resonanceB.findFirstShift(parentList=shiftList)
                if not shift:
                    continue
                ppm2 = shift.value

            delta = abs(ppm - ppm2)
            prevDelta = closestDict.get(peakDim)
            if (prevDelta is None) or (delta < prevDelta):
                closestDict[peakDim] = delta

            if delta > tolerance:
                continue

            matches.append((delta, resonanceB, uniqSpinSystem))

        # Best match has smallest delta
        if matches:
            matches.sort()
            delta, resonance, uniqSpinSystem = matches[0]

            prevDelta, peakDimB, ss = matchDict.get(resonance,
                                                    (None, None, None))
            if not peakDimB or (delta < prevDelta):
                matchDict[resonance] = (delta, peakDim, uniqSpinSystem)

    uniqResonanceDict = {}
    for resonance in matchDict.keys():
        delta, peakDim, uniqSpinSystem = matchDict[resonance]
        uniqResonanceDict[peakDim] = resonance, uniqSpinSystem

    # E.g. go through HNCA peaks and assign to
    # HNcoCA or iHNCA resonances if required
    nonMatched = {}
    for peakDim, atomType, contrib, isotope, isInter, ppm in peakTypes:
        if isInter is not None:
            continue

        if closestDict.get(peakDim) is None:
            # No inter residue peaks at all
            intensity = peak.findFirstPeakIntensity(intensityType='height')

            if intensity:
                if not nonMatched.has_key(atomType):
                    nonMatched[atomType] = []
                nonMatched[atomType].append(
                    (-abs(intensity.value), peakDim, contrib, isotope))

            continue

        match = uniqResonanceDict.get(peakDim)
        if match:
            resonance, uniqSpinSystem = match

            if tolerances:
                tolerance = tolerances[isotope]
            else:
                tolerance = getAnalysisDataDim(peakDim.dataDim).assignTolerance

            # untyped through-carbonyl resonance can interit type
            # by matching typed peaks

            if atomType and not resonance.assignNames:
                resonance.addAssignName(atomType)

            # e.g. the HNcoCA resonance is the one to put on this HNCA peak
            if contrib:
                if contrib.resonance is not resonance:
                    clearPeakDim(peakDim)
                    assignResToDim(peakDim, resonance, tolerance=tolerance)
            else:
                assignResToDim(peakDim, resonance, tolerance=tolerance)

        else:
            # No match to an unambig peak
            # store to work out which is best for each atom type
            # e.g. just in case we have two intra residue CA possibilites
            if not nonMatched.has_key(atomType):
                nonMatched[atomType] = []

            nonMatched[atomType].append(
                (closestDict[peakDim], peakDim, contrib, isotope))

    for atomType in nonMatched.keys():

        if (atomType in intraResonances) and (atomType in interResonances):
            # Both resonances already found, peak is spurious
            continue

        if (atomType in intraResonances) and (atomType not in interResonances):
            # E.g. there was iHNCA but no HNcoCA
            otherSpinSystem = prevSpinSystem

        elif (atomType not in intraResonances) and (atomType
                                                    in interResonances):
            # E.g. there was HNcoCA but no iHNCA
            otherSpinSystem = spinSystem

        else:
            # No info
            continue

        peakDimList = nonMatched[atomType]
        peakDimList.sort()
        # Assume that if we have two possible ambiguous peaks
        # for any given atom type, then the one furthest from an
        # unambigous peak is the best to take
        deltaPpm, peakDim, contrib, isotope = peakDimList[-1]

        if tolerances:
            tolerance = tolerances[isotope]
        else:
            tolerance = getAnalysisDataDim(peakDim.dataDim).assignTolerance

        # E.g. this HNCA peak matches no HNcoCA/iHNCA resonances
        resonance = None
        if contrib:
            resonance = contrib.resonance

        if resonance:
            # Already have an assignment
            spinSystem2 = resonance.resonanceGroup
            if spinSystem2 is None:
                addSpinSystemResonance(otherSpinSystem, resonance)

            elif spinSystem2 is not otherSpinSystem:
                resonance = nmrProject.newResonance(isotopeCode=isotope)
                addSpinSystemResonance(otherSpinSystem, resonance)
                clearPeakDim(peakDim)
                contrib = assignResToDim(peakDim,
                                         resonance,
                                         tolerance=tolerance)

        else:
            # Needs a new assignment
            for resonance2 in otherSpinSystem.resonances:
                if atomType in resonance2.assignNames:
                    resonance = resonance2
                    break

            if not resonance:
                resonance = nmrProject.newResonance(isotopeCode=isotope)
                contrib = assignResToDim(peakDim,
                                         resonance,
                                         tolerance=tolerance)
                addSpinSystemResonance(otherSpinSystem, resonance)

        if not contrib:
            # Resonance has come from the spin system due to its atomTypes
            contrib = assignResToDim(peakDim,
                                     resonance,
                                     tolerance=2 * tolerance)

        if not contrib:
            # Existing resonance on spin system was too far away
            resonance = nmrProject.newResonance(isotopeCode=isotope)
            contrib = assignResToDim(peakDim, resonance, tolerance=tolerance)
            addSpinSystemResonance(otherSpinSystem, resonance)

        if atomType:
            assignNames = (atomType, )
        else:
            assignNames = []

        if not resonance.assignNames:
            assignResonanceType(resonance, assignNames=assignNames)