Пример #1
0
def findPeaks(spec, numberOfPeaks, verbose=False):  #{{{
    """
    DEPRECIATED! 

    Find the position of the peaks and valleys of the EPR spectrum given the number of peaks to look for. 
    The function returns the total peak to peak width of the spectrum, given more than one peak, as well as the center field and linewidth.

    args:
    spec - an nddata set of the EPR spectrum. The EPR spectrum should be the data and the field values should be placed in an axis named 'field'
    numberOfPeaks - an integer. The number of peaks to find, for nitroxide this should be 3.

    """
    print "'findPeaks()' DEPRECIATED use 'findPeaksSequential()'"
    peaks = []
    valleys = []
    hrf = linspace(
        spec.getaxis('field').min(),
        spec.getaxis('field').max(), 10000)
    smash = spec.copy().interp('field', hrf).runcopy(
        real
    )  # use an interpolated higher res spec to get a more accurate esitmate of linewidth
    hrs = smash.copy()
    #smash -= average(spec.data)
    for i in range(numberOfPeaks):
        peak = smash.data.argmax()
        peaks.append(peak)
        valley = smash.data.argmin()
        valleys.append(valley)
        # remove from peak
        #find the high bound
        notCrossed = True
        count = 0
        dimSize = len(smash.data)
        while notCrossed:
            if peak + count <= 0:
                lowBound = peak + count
                notCrossed = False
            else:
                if float(smash['field', peak + count].data) <= 0.0:
                    lowBound = peak + count
                    notCrossed = False
            count -= 1
        # find the low bound
        notCrossed = True
        count = 0
        while notCrossed:
            if peak + count >= dimSize:  # check to make sure you haven't wandered off the spectrum
                highBound = peak + count
                notCrossed = False
            else:
                if float(smash['field', peak + count].data) <= 0.0:
                    highBound = peak + count
                    notCrossed = False
            count += 1
        smash['field', lowBound:highBound] = 0.0

        # remove from valley
        #find the high bound
        notCrossed = True
        count = 0
        while notCrossed:
            if valley + count <= 0:
                lowBound = valley + count
                notCrossed = False
            else:
                if float(smash['field', valley + count].data) >= 0.0:
                    lowBound = valley + count
                    notCrossed = False
            count -= 1
        # find the low bound
        notCrossed = True
        count = 0
        while notCrossed:
            if valley + count >= dimSize:  # check to make sure you haven't wandered off the spectrum
                highBound = valley + count
                notCrossed = False
            else:
                if float(smash['field', valley + count].data) >= 0.0:
                    highBound = valley + count
                    notCrossed = False
            count += 1
        smash['field', lowBound:highBound] = 0.0
        if verbose:
            pys.plot(smash)
    peak = pys.nddata(hrs.data[peaks]).rename('value', 'field').labels(
        'field',
        hrs.getaxis('field')[peaks])
    valley = pys.nddata(hrs.data[valleys]).rename('value', 'field').labels(
        'field',
        hrs.getaxis('field')[valleys])
    # Calculate relevant parameters
    peak.sort('field')
    valley.sort('field')
    return peak, valley
Пример #2
0
            currAmp = currTable.getaxis('amp')[currIndex[0]]
            waveSlice = saveTable.data[currIndex]


        ampList.append(currAmp)                   # calculate new amplitude and phase values
        print currPhase
        phaseList.append(currPhase)
        foundWaveform.append(waveSlice)

print "Loop took %0.2f seconds"%(time.time()-start)
foundWaveform = pys.nddata(array(foundWaveform)).rename('value','t').labels('t',waveform.getaxis('t'))
phaseList = array(phaseList)
ampList = array(ampList)

figure()
pys.plot(foundWaveform.runcopy(real),'b.',alpha=0.3,label='located')
pys.plot(foundWaveform.runcopy(real),'b--',alpha=0.3)
pys.plot(waveform.runcopy(real),'bo',alpha=0.3,label='target')
pys.plot(foundWaveform.runcopy(imag),'r.',alpha=0.3)
pys.plot(foundWaveform.runcopy(imag),'r--',alpha=0.3)
pys.plot(waveform.runcopy(imag),'ro',alpha=0.3)
legend()

# track phase and amplitude
figure()
pys.image(lookupTable)
plot(phaseList,ampList,'g.',alpha=0.3,markersize=10)
plot(phaseList,ampList,'k--',alpha=0.5)
ylim(ampList.min(),ampList.max())
xlim(phaseList.min(),phaseList.max())
Пример #3
0
def workupCwEpr(eprName,
                spectralWidthMultiplier=1.25,
                numPeaks=3,
                EPRCalFile=False,
                firstFigure=[]):  #{{{ EPR Workup stuff
    """
    This is a beast of a function...
    Perform the epr baseline correction and double integration.

    Args:
    eprName - string - full name of the EPR file without the file extension.
    spectralWidthMultiplier - a multiplier to determine the integration width based on the width of the spectrum (difference between lowField and highField peak)
    numPeaks - the number of peaks of the spectrum
    EPRCalFile - a calibration file in csv format
    firstFigure - a figure list instance (see fornotebook)

    Returns:
    spec - nddata - the EPR spectra with other info set to the EPR params dict.
    lineWidths - list - the EPR linewidths
    spectralWidth - double - the EPR peak to peak spectral width
    centerField - double - the centerfield
    doubleIntZC - nddata - the double integral spectrum
    doubleIntC3 - nddata - the double integral spectrum with cubic baseline correction
    diValue     - float  - the double integral value
    spinConc    - float  - the spin concentration from the double integral. Must have an EPRCalFile
    amplitudes  - array  - amplitude of each peak in the spectrum
    """
    firstFigure.append(
        {'print_string': r'\subparagraph{EPR Spectra %s}' % eprName + '\n\n'})
    eprFileName = eprName.split('\\')[-1]
    # Pull the specs, Find peaks, valleys, and calculate things with the EPR spectrum.#{{{
    spec, normalized = returnEPRSpec(eprName, resample=True)
    peak, valley = findPeaks(spec, numPeaks)
    lineWidths = valley.getaxis('field') - peak.getaxis('field')
    amplitudes = peak.data - valley.data
    spectralWidth = peak.getaxis('field').max() - peak.getaxis('field').min()
    # determine the center field
    if numPeaks == 2:
        centerField = (peak.getaxis('field')[0] + lineWidths[0] / 2. +
                       peak.getaxis('field')[1] + lineWidths[1] / 2.) / 2.
    elif numPeaks == 3:
        centerField = peak.getaxis('field')[1] + lineWidths[1] / 2.
    specStart = centerField - spectralWidthMultiplier * spectralWidth
    specStop = centerField + spectralWidthMultiplier * spectralWidth
    print "\nI calculate the spectral width to be: ", spectralWidth, " G \n"
    print "I calculate the center field to be: ", centerField, " G \n"
    print "I set spectral bounds of: ", specStart, " and ", specStop, " G \n"  #}}}
    if normalized == 'bad':
        print "The spectra is not normalized by the receiver gain"

    # Baseline correct the spectrum #{{{
    baseline1 = spec['field', lambda x: x < specStart].copy()
    baseline2 = spec['field', lambda x: x > specStop].copy()
    specBase = array(list(baseline1.data) + list(baseline2.data))
    fieldBase = array(
        list(baseline1.getaxis('field')) + list(baseline2.getaxis('field')))
    specBase = pys.nddata(specBase).rename('value',
                                           'field').labels('field', fieldBase)
    ### Calculate 0th, 1st, and 3rd order baselines
    baseline = average(specBase.data)
    spec.data -= baseline  # zeroth order correct the spectrum

    # Plot the results
    firstFigure = pys.nextfigure(firstFigure, 'EPRSpectra')
    pys.plot(spec, 'm', alpha=0.6)
    pys.plot(peak, 'ro', markersize=10)
    pys.plot(valley, 'ro', markersize=10)
    pys.plot(spec['field', lambda x: logical_and(x > specStart, x < specStop)],
             'b')
    pys.title('Integration Window')
    pys.ylabel('Spectral Intensity')
    pys.xlabel('Field (G)')
    pys.giveSpace(spaceVal=0.001)
    #}}}

    ### Take the first integral #{{{
    absorption = spec.copy().integrate('field')  #}}}

    # Fit the bounds of the absorption spec to a line and subtract from absorption spectrum.#{{{
    baseline1 = absorption['field', lambda x: x < specStart]
    baseline2 = absorption['field', lambda x: x > specStop]
    fieldBaseline = array(
        list(baseline1.getaxis('field')) + list(baseline2.getaxis('field')))
    baseline = pys.concat([baseline1, baseline2], 'field')
    baseline.labels('field', fieldBaseline)
    # Do the first order correction
    c1, fit1 = baseline.polyfit('field', order=1)
    fit1 = pys.nddata(
        array(c1[0] + absorption.getaxis('field') * c1[1])).rename(
            'value', 'field').labels('field', absorption.getaxis('field'))
    correctedAbs1st = absorption.runcopy(real) - fit1.runcopy(real)
    c3, fit3 = baseline.polyfit('field', order=3)
    fit3 = pys.nddata(
        array(c3[0] + absorption.getaxis('field') * c3[1] +
              (absorption.getaxis('field')**2) * c3[2] +
              (absorption.getaxis('field')**3) * c3[3])).rename(
                  'value', 'field').labels('field',
                                           absorption.getaxis('field'))
    correctedAbs3rd = absorption.runcopy(real) - fit3.runcopy(real)
    #}}}

    # Set the values of absorption spec outside of int window to zero.#{{{
    zeroCorr = correctedAbs1st.copy()
    zeroCorr['field', lambda x: x < specStart] = 0.0
    zeroCorr['field', lambda x: x > specStop] = 0.0  #}}}

    # Plot absorption results#{{{
    firstFigure = pys.nextfigure(firstFigure, 'Absorption')
    pys.plot(absorption, label='uncorrected')
    pys.plot(fit1, label='1st order fit')
    pys.plot(fit3, label='3rd order fit')
    pys.plot(correctedAbs1st, label='1st corr')
    pys.plot(correctedAbs3rd, label='3rd corr')
    pys.plot(zeroCorr, label='zero cut')
    pys.title('Absorption Spectrum')
    pys.ylabel('Absorptive Signal')
    pys.xlabel('Field (G)')
    pys.giveSpace(spaceVal=0.001)
    pys.legend()
    #}}}

    # Calculate and plot the double integral for the various corrections you've made #{{{
    doubleInt = absorption.copy().integrate('field')
    doubleIntC1 = correctedAbs1st.copy().integrate('field')
    doubleIntC3 = correctedAbs3rd.copy().integrate('field')
    doubleIntZC = zeroCorr.copy().integrate('field')
    diValue = doubleIntC3.data.max()
    print "\nI calculate the double integral to be: %0.2f\n" % diValue

    firstFigure = pys.nextfigure(firstFigure, 'DoubleIntegral')
    pys.plot(doubleInt, label='uncorrected')
    pys.plot(doubleIntC1, label='1st corrected')
    pys.plot(doubleIntC3, label='3rd corrected')
    pys.plot(doubleIntZC, label='zero corrected')
    pys.legend(loc=2)
    pys.title('Double Integral Results')
    pys.ylabel('Second Integral (arb)')
    pys.xlabel('Field (G)')
    pys.giveSpace(spaceVal=0.001)
    #}}}

    # If the calibration file is present use that to calculate spin concentration#{{{
    if normalized == 'good':
        if EPRCalFile:
            calib = calcSpinConc(EPRCalFile)
            ### Fit the series and calculate concentration
            c, fit = calib.polyfit('concentration')
            spinConc = (diValue - c[0]) / c[1]
            # Plotting
            firstFigure = pys.nextfigure(firstFigure, 'SpinConcentration')
            pys.plot(calib, 'r.', markersize=15)
            pys.plot(fit, 'g')
            pys.plot(spinConc, diValue, 'b.', markersize=20)
            pys.title('Estimated Spin Concentration')
            pys.xlabel('Spin Concentration')
            pys.ylabel('Double Integral')
            ax = pys.gca()
            ax.text(spinConc,
                    diValue - (0.2 * diValue),
                    '%0.2f uM' % spinConc,
                    color='blue',
                    fontsize=15)
            pys.giveSpace()
        else:
            spinConc = None
            #}}}
    return spec, lineWidths, spectralWidth, centerField, doubleIntZC, doubleIntC3, diValue, spinConc, amplitudes
            tempThreshold+=0.01
            ampVals,phaseVals = where(currTable.data<=tempThreshold) # find values in given range.
        phaseIndex = argmin(abs(phaseVals-currIndex[1]))    # get index of phase and amp that is closest to previous value.
        ampIndex = argmin(abs(ampVals-currIndex[0]))
        currIndex = (ampVals[ampIndex],phaseVals[phaseIndex])                   # reset the index
        ampList.append(lookupTable.getaxis('amp')[ampVals[ampIndex]])                   # calculate new amplitude and phase values
        phaseList.append(lookupTable.getaxis('phase')[phaseVals[phaseIndex]])
        foundWaveform.append(lookupTable.data[currIndex])

print "Loop took %0.2f seconds"%(time.time()-start)
foundWaveform = pys.nddata(array(foundWaveform)).rename('value','t').labels('t',waveform.getaxis('t'))
phaseList = array(phaseList)
ampList = array(ampList)

figure()
pys.plot(foundWaveform)
pys.plot(waveform)

# track phase and amplitude
figure()
pys.image(lookupTable)
plot(phaseList,ampList,'g.',markersize=10)
plot(phaseList,ampList,'k--',alpha=0.5)
ylim(ampList.min(),ampList.max())
xlim(phaseList.min(),phaseList.max())

xbandWave = pys.nddata(array(ampList)*exp(1j*array(phaseList)*pi/180)).rename('value','t').labels('t',waveform.getaxis('t'))
figure()
pys.plot(xbandWave,label='real')
pys.plot(xbandWave.runcopy(imag),label='imag')
legend()
Пример #5
0
modulation = pys.nddata(2*pi*(-freqWidth*timeAxis + rate/2*timeAxis**2)).rename('value','t').labels(['t'],[timeAxis])
# this is the frequency modulation
chirp = pys.nddata(exp(1j*modulation.data)).rename('value','t').labels(['t'],[timeAxis])
planeWave = pys.nddata(exp(1j*2*pi*freqOffset*timeAxis)).rename('value','t').labels(['t'],[timeAxis])

#{{{
outputData = pullCsvData(outputDataFile,3)
outputData = pys.nddata(outputData[:,0]+1j*outputData[:,1]).rename('value','digAmp').labels('digAmp',outputData[:,2])
# take only what we can use and set to full scale
outputClean = outputData['digAmp',lambda x: logical_and(x>=dynamicRangeMin,x<=dynamicRangeMax)]
# Clean up the amplitude
outputAmp = outputClean.runcopy(abs)
outputAmp.data -= outputAmp.data.min()
outputAmp /= outputAmp.data.max()
pys.figure()
pys.plot(outputData.runcopy(abs))
pys.plot(outputAmp.runcopy(abs))
# calculate the phase roll at given amp, unwrap the roll so we can interpolate.
outputClean.data = arctan2(outputClean.runcopy(imag).data,outputClean.runcopy(real).data)
outputClean.data = unwrap(outputClean.data)
pys.figure()
pys.plot(outputClean,'r.')
pys.title('phase roll')#}}}
# amplitude modulation
sinMod = pys.nddata(sin(pi/chirpLength*timeAxis)).rename('value','t').labels(['t'],[timeAxis])
# the corrected amplitude
correctedDigAmp = nddata(interp(sinMod.data,outputAmp.data,outputAmp.getaxis('digAmp'))).rename('value','t').labels('t',timeAxis)
# the phase roll for our amplitude input
phaseRoll = nddata(interp(correctedDigAmp.data,outputClean.getaxis('digAmp'),outputClean.data)).rename('value','t').labels('t',timeAxis)
pys.figure()
pys.plot(phaseRoll)
Пример #6
0
collection = db.localDataRevisedDataLayout  # This is my test collection#}}}

dataSet = list(collection.find({'expName':
                                '150529_CheYPep_N62C_5MUrea_ODNP'}))[0]
epr = dtb.dictToNdData('cwEPR', dataSet)

t1Data = dtb.dictToNdData('t1PowerODNP', dataSet)
t1Data.sort('power')
t1fits = dataSet.get('data').get('t1PowerODNP').get('fitList')
powerArray = pys.r_[t1Data.getaxis('power').min():t1Data.getaxis('power').max(
):100j]
t1Fit = pys.nddata(t1fits[0] + t1fits[1] * powerArray).rename(
    'value', 'power').labels('power', powerArray)

pys.figure()
pys.plot(t1Data)
pys.plot(t1Fit)

kSigmaData = dtb.dictToNdData('kSigmaODNP', dataSet, retValue=False)
powerArray = pys.r_[kSigmaData.getaxis('power').min():kSigmaData.
                    getaxis('power').max():100j]
ksFits = dataSet.get('data').get('kSigmaODNP').get('fitList')
kSigmaFit = pys.nddata(ksFits[0] / (ksFits[1] + powerArray) *
                       powerArray).rename('value',
                                          'power').labels('power', powerArray)

pys.figure()
pys.plot(kSigmaData)
pys.plot(kSigmaFit)

pys.show()
Пример #7
0
    centerField = peak.getaxis('field')[1] + lineWidths[1]/2.# assuming the center point comes out in the center. The way the code is built this should be robust
    specStart = centerField - spectralWidth
    specStop = centerField + spectralWidth
    print "\nI calculate the spectral width to be: ",spectralWidth," G \n"
    print "I calculate the center field to be: ",centerField," G \n"
    print "I set spectral bounds of: ", specStart," and ", specStop," G \n"#}}}

    # Baseline correct the spectrum #{{{
    baseline1 = spec['field',lambda x: x < specStart].copy().mean('field')
    baseline2 = spec['field',lambda x: x > specStop].copy().mean('field')
    baseline = average(array([baseline1.data,baseline2.data]))
    spec.data -= baseline

    # Plot the results
    fl.figurelist = pys.nextfigure(fl.figurelist,'EPRSpectra')
    pys.plot(spec,'m',alpha=0.6)
    pys.plot(peak,'ro',markersize=10)
    pys.plot(valley,'ro',markersize=10)
    pys.plot(spec['field',lambda x: logical_and(x>specStart,x<specStop)],'b')
    pys.title('Integration Window')
    pys.ylabel('Spectral Intensity')
    pys.xlabel('Field (G)')
    pys.giveSpace(spaceVal=0.001)
    #}}}

    ### Take the first integral #{{{
    absorption = spec.copy().integrate('field')#}}}

    # Fit the bounds of the absorption spec to a line and subtract from absorption spectrum.#{{{
    baseline1 = absorption['field',lambda x: x < specStart]
    baseline2 = absorption['field',lambda x: x > specStop]
    output = output['phase',0:2]
else:
    output = saveOutput.copy()

#start = 13822e-9-(len(ampArray)*100e-9)
start = 1112e-9
width = 100e-9
bufferVal = 25e-9
# now calculate the phase and amplitude of each time increment.
if reCalcData:
    data = pys.ndshape([len(ampArray),len(phaseArray)],['amp','phase'])
    data = data.alloc(dtype='complex')
    data.labels(['amp','phase'],[ampArray,phaseArray])#}}}
    expOutput = []
    pys.figure()
    pys.plot(output['phase',0])
    for countPhase,phase in enumerate(output.getaxis('phase')):
        print "Analyzing phase %i of %i"%(countPhase,len(output.getaxis('phase')))
        for countAmp,amp in enumerate(ampArray):
            currSlice = output['phase',countPhase,'t',lambda x: logical_and(x > start + width*countAmp + bufferVal, x < start + width*(countAmp+1) - bufferVal)]
            data['amp',countAmp,'phase',countPhase] = currSlice.copy().mean('t').data
            if debug:
                pys.plot(currSlice,'r')
    pys.title('Pulse trace')
    pys.xlabel('time (us)')
    pys.ylabel('amplitude')
    pys.tight_layout()
    pys.savefig('pulseTrace.png')


pys.figure()
         currTable -= dataVal
         print "found edge case low bound is now %0.2f and high bound is %0.2f"%(lowBound,highBound)
     else:
         currTable = lookupTable['phase',lambda x: logical_and(x >= lowBound, x <= highBound)].copy() - dataVal
         currTable = currTable['amp',lambda x: logical_and(x>=ampLowBound,x<=ampHighBound)] 
     phaseLowBounds.append(lowBound)
     phaseHighBounds.append(highBound)
     minimaIndex = unravel_index(argmin(currTable.runcopy(abs).data),shape(currTable.data)) 
     amp = lookupTable.getaxis('amp')[minimaIndex[0]]
     phase = lookupTable.getaxis('phase')[minimaIndex[1]]
     locatedData.append(lookupTable.data[minimaIndex])
     ampList.append(amp)
     phaseList.append(phase)
 print "Search loop for waveform took: ",time.time()-start
 print "Size of search table is: ",shape(currTable.data)
 pys.plot(array(phaseList),array(ampList),'o',markersize=5)
 pys.plot(array(phaseList),array(ampList),'--')
 locatedData = pys.nddata(array(locatedData)).rename('value','t').labels('t',waveform.getaxis('t'))
 interpolatedWaveform = pys.nddata(array(ampList)*exp(1j*(pi*array(phaseList)/180))).rename('value','t').labels('t',waveform.getaxis('t'))
 smoothedData = correctedData.copy().convolve('t',5e-9)
 ### Calculate the phase and amplitude jumps.
 phases = []
 amps = []
 for count in range(len(phaseList)-1):
     phases.append(phaseList[count]-phaseList[count+1])
     amps.append(ampList[count]-ampList[count+1])
 figure()
 plot(waveform.getaxis('t')[0:-1],array(phases),label='phaseDiff')
 plot(waveform.getaxis('t')[0:-1],array(amps),label='ampDiff')
 legend()
 title('Phase and amplitude Jumps')
Пример #10
0
import pymongo
import matlablike as pys
import nmrfit

pys.close('all')
MONGODB_URI = 'mongodb://*****:*****@ds047040.mongolab.com:47040/magresdata'  # This is the address to the database hosted at MongoLab.com
# Make the connection to the server as client
conn = pymongo.MongoClient(
    MONGODB_URI)  # Connect to the database that I purchased
db = conn.magresdata
collection = db.hanLabODNPTest  # This is my test collection

searchDict = {
    'spinLabel': 'MTSL',
    'osmolyte': 'None',
    'osmolyteConcentration': 'None',
    'macroMolecule': 'CheY',
    'bindingPartner': 'P2'
}  #,'repeat':'0'}#,{'spinLabel':'MTSL','osmolyte':'urea','osmolyteConcentration':'5M','macroMolecule':'CheY','repeat':'0'}]
listOfSets = list(
    collection.find(searchDict)
)  # this gives me a list of dictionaries from the collection that satisfy the constraints imposed by my search dictionary.

dataTag = 'kSigma'  # This defines what data I pull from the database
data = dtb.dictToNdData(dataTag, listOfSets[0], retValue=False)
data = nmrfit.ksp(data)
data.fit()
pys.plot(data)
pys.plot(data.eval(100))
pys.show()
Пример #11
0
                currIndex = (currIndex[0],len(lookupTable.getaxis('phase'))-1)
            currTable = currTable['phase',currIndex[1]-maxIndexShift:currIndex[1]]
            minimaIndex = unravel_index(argmin(currTable.runcopy(abs).data),shape(currTable.data)) 
            currIndex = (minimaIndex[0],minimaIndex[1]+(currIndex[1]-maxIndexShift))                        # you cut the phase indecies by currIndex, now add it back

        ampList.append(lookupTable.getaxis('amp')[currIndex[0]])                   # calculate new amplitude and phase values
        phaseList.append(lookupTable.getaxis('phase')[currIndex[1]])
        foundWaveform.append(lookupTable.data[currIndex])

print "Loop took %0.2f seconds"%(time.time()-start)
foundWaveform = pys.nddata(array(foundWaveform)).rename('value','t').labels('t',waveform.getaxis('t'))
phaseList = array(phaseList)
ampList = array(ampList)

figure()
pys.plot(foundWaveform)
pys.plot(waveform)

# track phase and amplitude
figure()
pys.image(lookupTable)
plot(phaseList,ampList,'g.',markersize=10)
plot(phaseList,ampList,'k--',alpha=0.5)
ylim(ampList.min(),ampList.max())
xlim(phaseList.min(),phaseList.max())

xbandWave = pys.nddata(array(ampList)*exp(1j*array(phaseList)*pi/180)).rename('value','t').labels('t',waveform.getaxis('t'))
if convolveOutput:
    toSynthesize=xbandWave.copy().convolve('t',timeResolution*2)
else:
    toSynthesize=xbandWave.copy()
Пример #12
0
    'value',
    'time')  # change the dimension label from the default 'value' to 'time'
waveform.labels('time', x)  # give the 'time' dimension labels
# Note I could do this in one line as waveform = ps.nddata(y).rename('value','time').labels('time',x)

# lets generate some error for the data set.
error = np.random.random(len(y)) * 0.01

waveform.set_error(
    error
)  # throw the error into the dataset. Note you can also assign error to a dimension by 'set_error('dimName',arrayOfError)'

# plot the data
ps.figure()
ps.plot(
    waveform
)  # note here plot is superloaded to handle nddata instead of the usual plot(x,y). Note this is a wrapper for the standard plot function and passes all arguements onto matplotlib.
ps.title('My Initial Waveform')

#################################################################################
### Lets manipulate the data set now.
#################################################################################

# make a copy of the data set
pulse = waveform.copy()
# make a square pulse by setting anything before 10s and after 20s to zero
pulse['time', lambda x: x < 10.] = 0.0
pulse['time', lambda x: x > 20.] = 0.0

# plot the pulse
ps.figure()