B', 1, 1, 8)[0]]
+ NDIM = multiUP(header, '>B', 1, 1, 12)[0]
#data_dimension_exist = multiUP(header,'>B', 1, 1, 13)[0]
#data_type = multiUP(header,'>B', 1, 1, 14)[0]
#translate = multiUP(header,'>B', 1, 8, 16)
- dataType = multiUP(header,'>B', 1, 8, 24)
- dataUnits = multiUP(header,'>B', 1, 16, 32).reshape(8, 2)
- NP = multiUP(header,'>I', 4, 8, 176)
- dataStart = multiUP(header,'>I', 4, 8, 208)
- dataStop = multiUP(header,'>I', 4, 8, 240)
- axisStart = multiUP(header,'>d', 8, 8, 272)
- axisStop = multiUP(header,'>d', 8, 8, 336)
- baseFreq = multiUP(header,'>d', 8, 8, 1064)
+ dataType = multiUP(header, '>B', 1, 8, 24)
+ dataUnits = multiUP(header, '>B', 1, 16, 32).reshape(8, 2)
+ NP = multiUP(header, '>I', 4, 8, 176)
+ dataStart = multiUP(header, '>I', 4, 8, 208)
+ dataStop = multiUP(header, '>I', 4, 8, 240)
+ axisStart = multiUP(header, '>d', 8, 8, 272)
+ axisStop = multiUP(header, '>d', 8, 8, 336)
+ baseFreq = multiUP(header, '>d', 8, 8, 1064)
#zero_point = multiUP(header,'>d', 8, 8, 1128)
- reverse = multiUP(header,'>B', 1, 8, 1192)
- paramStart = multiUP(header,'>I', 4, 1, 1212)[0]
- paramLength = multiUP(header,'>I', 4, 1, 1216)[0]
- readStart = multiUP(header,'>I', 4, 1, 1284)[0]
+ reverse = multiUP(header, '>B', 1, 8, 1192)
+ paramStart = multiUP(header, '>I', 4, 1, 1212)[0]
+ paramLength = multiUP(header, '>I', 4, 1, 1216)[0]
+ readStart = multiUP(header, '>I', 4, 1, 1284)[0]
#data_length = multiUP(header,'>Q', 8, 1, 1288)[0]
- hdrPars = getJEOLpars(filePath,endian,paramStart,paramLength)
+ hdrPars = getJEOLpars(filePath, paramStart, paramLength)
dFilter = getJEOLdFilter(hdrPars)
-
loadSize = np.prod(NP[:NDIM])
if NDIM == 1 and (dataType[0] == 3 or dataType[0] == 4): #Complex 1D
loadSize *= 2
@@ -467,23 +672,22 @@ def loadJEOLDelta(filePath):
data = data[:int(loadSize/2)] - 1j * data[int(loadSize/2):]
data = np.reshape(data, [int(NP[1] / Step), int(NP[0] / Step), Step, Step])
data = [np.concatenate(np.concatenate(data, 1), 1)]
- elif NDIM == 2 and dataType[0] == 3 and dataType[1] == 3 : #2D Complex-Complex (Hypercomplex)
+ elif NDIM == 2 and dataType[0] == 3 and dataType[1] == 3: #2D Complex-Complex (Hypercomplex)
hyper = np.array([0, 1])
Step = 32 # Step size of block
- tmp = np.split(data,4)
+ tmp = np.split(data, 4)
data = [tmp[0] - 1j * tmp[1], tmp[2] - 1j * tmp[3]]
del tmp
- for i in range(len(data)):
+ for i, _ in enumerate(data):
data[i] = np.reshape(data[i], [int(NP[1] / Step), int(NP[0] / Step), Step, Step])
data[i] = np.concatenate(np.concatenate(data[i], 1), 1)
-
eS = (slice(None),) #empty slice
for dim in range(NDIM): #Cut data for every dim
- useSlice = eS * (NDIM - dim - 1) +(slice(0,dataStop[dim] + 1,None),) + eS * dim
- for i in range(len(data)):
+ useSlice = eS * (NDIM - dim - 1) +(slice(0, dataStop[dim] + 1, None),) + eS * dim
+ for i, _ in enumerate(data):
data[i] = data[i][useSlice]
freq = baseFreq[0:NDIM][::-1] * 1e6
- spec = dataUnits[0:NDIM,1][::-1] != 28 #If not 28 (sec), then spec = true
+ spec = dataUnits[0:NDIM, 1][::-1] != 28 #If not 28 (sec), then spec = true
sw = []
ref = []
for axisNum in reversed(range(NDIM)):
@@ -491,7 +695,7 @@ def loadJEOLDelta(filePath):
axisScale = dataUnits[axisNum][0]
if axisType == 28: # Sec
scale = convJEOLunit(axisScale)
- dw = (axisStop[axisNum] - axisStart[axisNum]) / (dataStop[axisNum] + 1 - 1) * scale
+ dw = (axisStop[axisNum] - axisStart[axisNum]) / (dataStop[axisNum] + 1 - 1) * scale
sw.append(1.0 / dw)
ref.append(baseFreq[axisNum] * 1e6)
if axisType == 13: # Hz
@@ -502,15 +706,25 @@ def loadJEOLDelta(filePath):
sw.append(np.abs(axisStart[axisNum] - axisStop[axisNum]) * baseFreq[axisNum])
sidefreq = -np.floor((dataStop[axisNum] + 1) / 2) / (dataStop[axisNum] + 1) * sw[-1] # frequency of last point on axis
ref.append(sidefreq + baseFreq[axisNum] * 1e6 - axisStop[axisNum] * baseFreq[axisNum])
- for k in range(len(data)): #Flip LR if spectrum axis
+ for k, _ in enumerate(data): #Flip LR if spectrum axis
for i in range(NDIM):
if spec[-1 - i] == 1:
data[k] = np.flip(data[k], NDIM -1 - i)
- masterData = sc.Spectrum(hc.HComplexData(np.array(data), hyper), (filePath, None), freq, sw, spec, ref=ref, dFilter = dFilter)
+ masterData = sc.Spectrum(hc.HComplexData(np.array(data), hyper), (filePath, None), freq, sw, spec, ref=ref, dFilter=dFilter)
masterData.addHistory("JEOL Delta data loaded from " + filePath)
return masterData
def saveJSONFile(filePath, spectrum):
+ """
+ Saves a spectrumclass object to a .json file.
+
+ Parameters
+ ----------
+ filePath: string
+ Path to the file that should be created
+ spectrum: SpectrumClass
+ The spectrum class object
+ """
import json
struct = {}
item = spectrum.data
@@ -534,6 +748,19 @@ def saveJSONFile(filePath, spectrum):
json.dump(struct, outfile)
def loadJSONFile(filePath):
+ """
+ Loads a ssNake .json file.
+
+ Parameters
+ ----------
+ filePath: string
+ Path to the file that should be loaded
+
+ Returns
+ -------
+ SpectrumClass
+ SpectrumClass object of the loaded data
+ """
import json
with open(filePath, 'r') as inputfile:
struct = json.load(inputfile)
@@ -572,11 +799,24 @@ def loadJSONFile(filePath):
xaxA,
history=history,
metaData=metaData,
- dFilter = dFilter)
+ dFilter=dFilter)
masterData.addHistory("JSON data loaded from " + filePath)
return masterData
def saveMatlabFile(filePath, spectrum, name='spectrum'):
+ """
+ Saves a spectrumclass object to a .mat file.
+
+ Parameters
+ ----------
+ filePath: string
+ Path to the file that should be created
+ spectrum: SpectrumClass
+ The spectrum class object
+ name: string (optional)
+ Name of the data set within the .mat file
+
+ """
import scipy.io
struct = {}
struct['dim'] = spectrum.ndim()
@@ -596,6 +836,19 @@ def saveMatlabFile(filePath, spectrum, name='spectrum'):
scipy.io.savemat(filePath, matlabStruct)
def loadMatlabFile(filePath):
+ """
+ Loads a ssNake .mat file.
+
+ Parameters
+ ----------
+ filePath: string
+ Path to the file that should be loaded
+
+ Returns
+ -------
+ SpectrumClass
+ SpectrumClass object of the loaded data
+ """
import scipy.io
with open(filePath, 'rb') as inputfile: # read first several bytes the check .mat version
teststring = inputfile.read(13)
@@ -605,10 +858,10 @@ def loadMatlabFile(filePath):
var = [k for k in matlabStruct.keys() if not k.startswith('__')][0]
mat = matlabStruct[var]
if 'hyper' in mat.dtype.names:
- if len(mat['hyper'][0,0]) == 0:
+ if len(mat['hyper'][0, 0]) == 0:
hyper = [0]
else:
- hyper = mat['hyper'][0,0][0]
+ hyper = mat['hyper'][0, 0][0]
else:
hyper = None
if 'dFilter' in mat.dtype.names:
@@ -621,7 +874,7 @@ def loadMatlabFile(filePath):
data = np.array(mat['data'][0][0][0])
else:
data = np.array(mat['data'][0][0])
- xaxA = [k[0] for k in (mat['xaxArray'][0])]
+ xaxA = [k[0] for k in mat['xaxArray'][0]]
else:
if hyper is None: #If old format
data = np.array(mat['data'][0, 0])
@@ -661,8 +914,8 @@ def loadMatlabFile(filePath):
list(ref),
xaxA,
history=history,
- metaData = metaData,
- dFilter = dFilter)
+ metaData=metaData,
+ dFilter=dFilter)
masterData.addHistory("Matlab data loaded from " + filePath)
return masterData
else: # If the version is 7.3, use HDF5 type loading
@@ -728,14 +981,25 @@ def loadMatlabFile(filePath):
xaxA,
history=history,
metaData=metaData,
- dFilter = dFilter)
+ dFilter=dFilter)
masterData.addHistory("Matlab data loaded from " + filePath)
return masterData
def brukerTopspinGetPars(file):
- """ A routine to load all pars to a dictionary for Bruker Topsin acqus type
- file """
+ """
+ Loads Bruker Topspin parameter file.
+
+ Parameters
+ ----------
+ file: string
+ Path to the parameter file.
+
+ Returns
+ -------
+ dict:
+ Dictionary with all parameters
+ """
with open(file, 'r') as f:
data = f.read().split('\n')
pos = 0
@@ -749,9 +1013,9 @@ def brukerTopspinGetPars(file):
if val[0] == '<':
val = val.strip('<>')
elif val[0] == '(': #If list of values (always int/floats)
- pos +=1
+ pos += 1
val = []
- while not data[pos].startswith('##$'):
+ while not data[pos].startswith('##$') and not data[pos].startswith('$$'):
try:
val = val + [float(x) for x in data[pos].strip('<>').split()]
except Exception:
@@ -772,12 +1036,25 @@ def brukerTopspinGetPars(file):
return pars
def getBrukerFilter(pars):
+ """
+ Get phase delay of a Bruker topspin data set.
+
+ Parameters
+ ----------
+ pars: dict
+ Dictionary holding the parameters
+
+ Returns
+ -------
+ float:
+ Phase delay (first order phasing correction) of the data
+ """
delay = -1
if 'GRPDLY' in pars.keys():
delay = pars['GRPDLY'] * 2 * np.pi
if delay >= 0.0:
return delay
- elif pars['DSPFVS'] == 10 or pars['DSPFVS'] == 11 or pars['DSPFVS'] == 12: # get from table
+ if pars['DSPFVS'] == 10 or pars['DSPFVS'] == 11 or pars['DSPFVS'] == 12: # get from table
CorrectionList = [{'2': 44.7500, '3': 33.5000, '4': 66.6250, '6': 59.0833, '8': 68.5625, '12': 60.3750,
'16': 69.5313, '24': 61.0208, '32': 70.0156, '48': 61.3438, '64': 70.2578, '96': 61.5052,
'128': 70.3789, '192': 61.5859, '256': 70.4395, '384': 61.6263, '512': 70.4697, '768': 61.6465,
@@ -796,26 +1073,39 @@ def getBrukerFilter(pars):
def loadBrukerTopspin(filePath):
+ """
+ Loads Bruker Topspin/Xwinnmr data (i.e. time-domain data).
+
+ Parameters
+ ----------
+ filePath: string
+ Path to the file that should be loaded
+
+ Returns
+ -------
+ SpectrumClass
+ SpectrumClass object of the loaded data
+ """
if os.path.isfile(filePath):
Dir = os.path.dirname(filePath)
else:
Dir = filePath
pars = []
- for File in ['acqus','acqu2s','acqu3s']:
+ for File in ['acqus', 'acqu2s', 'acqu3s']:
if os.path.exists(Dir + os.path.sep + File):
pars.append(brukerTopspinGetPars(Dir + os.path.sep + File))
SIZE = [x['TD'] for x in pars]
FREQ = [x['SFO1'] * 1e6 for x in pars]
SW = [x['SW_h'] for x in pars]
REF = [x['O1'] for x in pars]
- ByteOrder = ['l','b'][pars[0]['BYTORDA']] #The byte orders that is used
+ ByteOrder = ['l', 'b'][pars[0]['BYTORDA']] #The byte orders that is used
REF = list(- np.array(REF) + np.array(FREQ))
dFilter = getBrukerFilter(pars[0])
totsize = np.prod(SIZE)
dim = len(SIZE)
directSize = int(np.ceil(float(SIZE[0]) / 256)) * 256 #Size of direct dimension including
#blocking size of 256 data points
- for file in ['fid','ser']:
+ for file in ['fid', 'ser']:
if os.path.exists(Dir + os.path.sep + file):
if file == 'ser':
totsize = int(totsize / SIZE[0]) * directSize #Always load full 1024 byte blocks (256 data points) for >1D
@@ -828,10 +1118,10 @@ def loadBrukerTopspin(filePath):
newSize[0] = int(directSize / 2)
ComplexData = ComplexData.reshape(*newSize[-1::-1])
if dim == 2:
- ComplexData = ComplexData[:,0:int(SIZE[0]/2)] #Cut off placeholder data
+ ComplexData = ComplexData[:, 0:int(SIZE[0]/2)] #Cut off placeholder data
elif dim == 3:
- ComplexData = ComplexData[:,:,0:int(SIZE[0]/2)] #Cut off placeholder data
- masterData = sc.Spectrum(ComplexData, (filePath, None), FREQ[-1::-1], SW[-1::-1], [False] * dim, ref = REF[-1::-1], dFilter = dFilter)
+ ComplexData = ComplexData[:, :, 0:int(SIZE[0]/2)] #Cut off placeholder data
+ masterData = sc.Spectrum(ComplexData, (filePath, None), FREQ[-1::-1], SW[-1::-1], [False] * dim, ref = REF[-1::-1], dFilter=dFilter)
# TODO: Inserting metadata should be made more generic
try:
masterData.metaData['# Scans'] = str(pars[0]['NS'])
@@ -857,18 +1147,31 @@ def loadBrukerTopspin(filePath):
return masterData
def loadBrukerWinNMR(filePath):
+ """
+ Loads Bruker WinNMR data.
+
+ Parameters
+ ----------
+ filePath: string
+ Path to the file that should be loaded
+
+ Returns
+ -------
+ SpectrumClass
+ SpectrumClass object of the loaded data
+ """
base, extension = os.path.splitext(filePath)
#Check if upper or lower case
- names = ['.fqs','.aqs','.fid','.1r','.1i']
+ names = ['.fqs', '.aqs', '.fid', '.1r', '.1i']
if extension == extension.upper(): #If uppercase
names = [x.upper() for x in names]
present = [os.path.exists(base + x) for x in names]
- if extension == names[3] or extension == names[4]: #If spec loaded
+ if extension in (names[3], names[4]): #If spec loaded
pars = brukerTopspinGetPars(base + names[0])
SIZE = pars['XDIM']
- FREQ = pars['SF'] * 1e6
+ FREQ = pars['SF'] * 1e6
SW = pars['SW_p']
- ByteOrder = ['l','b'][pars['BYTORDP']] #The byte orders that is used
+ ByteOrder = ['l', 'b'][pars['BYTORDP']] #The byte orders that is used
OFFSET = pars['OFFSET']
pos = np.fft.fftshift(np.fft.fftfreq(SIZE, 1.0 / SW))[-1] #Get last point of axis
pos2 = OFFSET * 1e-6 * FREQ #offset in Hz
@@ -877,11 +1180,11 @@ def loadBrukerWinNMR(filePath):
else:
pars = brukerTopspinGetPars(base + names[1])
SIZE = pars['TD']
- FREQ = pars['SFO1'] * 1e6
+ FREQ = pars['SFO1'] * 1e6
SW = pars['SW_h']
- REF = pars['O1']
+ REF = pars['O1']
REF = - REF+ FREQ
- ByteOrder = ['l','b'][pars['BYTORDA']] #The byte orders that is used
+ ByteOrder = ['l', 'b'][pars['BYTORDA']] #The byte orders that is used
spec = False
if spec: #If spec loaded
with open(base + names[3], "rb") as f:
@@ -900,7 +1203,7 @@ def loadBrukerWinNMR(filePath):
raw = np.fromfile(f, np.float32, SIZE)
raw = raw.newbyteorder(ByteOrder) #Load with right byte order
ComplexData = np.array(raw[0:len(raw):2]) + 1j * np.array(raw[1:len(raw):2])
- masterData = sc.Spectrum(ComplexData, (filePath, None), [FREQ], [SW], [spec], ref = [REF])
+ masterData = sc.Spectrum(ComplexData, (filePath, None), [FREQ], [SW], [spec], ref=[REF])
if not spec:
try:
masterData.metaData['# Scans'] = str(pars['NS'])
@@ -915,12 +1218,25 @@ def loadBrukerWinNMR(filePath):
return masterData
def loadBrukerSpectrum(filePath):
+ """
+ Loads Bruker spectrum data (processed data). Supports 1-3D.
+
+ Parameters
+ ----------
+ filePath: string
+ Path to the file that should be loaded
+
+ Returns
+ -------
+ SpectrumClass
+ SpectrumClass object of the loaded data
+ """
if os.path.isfile(filePath):
Dir = os.path.dirname(filePath)
else:
Dir = filePath
pars = []
- for File in ['procs','proc2s','proc3s']:
+ for File in ['procs', 'proc2s', 'proc3s']:
if os.path.exists(Dir + os.path.sep + File):
pars.append(brukerTopspinGetPars(Dir + os.path.sep + File))
SIZE = [x['SI'] for x in pars]
@@ -928,17 +1244,16 @@ def loadBrukerSpectrum(filePath):
SW = [x['SW_p'] for x in pars]
FREQ = [x['SF'] * 1e6 for x in pars]
OFFSET = [x['OFFSET'] for x in pars]
- ByteOrder = ['l','b'][pars[0]['BYTORDP']] #The byte orders that is used
-
+ ByteOrder = ['l', 'b'][pars[0]['BYTORDP']] #The byte orders that is used
REF = []
- for index in range(len(SIZE)): #For each axis
+ for index, _ in enumerate(SIZE): #For each axis
pos = np.fft.fftshift(np.fft.fftfreq(SIZE[index], 1.0 / SW[index]))[-1] #Get last point of axis
pos2 = OFFSET[index] * 1e-6 * FREQ[index] #offset in Hz
REF.append(FREQ[index] + pos - pos2)
- totsize = np.prod(SIZE)
+ totsize = np.prod(SIZE)
dim = len(SIZE)
DATA = []
- files = [['1r','1i'],['2rr','2ir','2ri','2ii'],['3rrr','3irr','3rir','3iir','3rri','3iri','3rii','3iii']]
+ files = [['1r','1i'], ['2rr', '2ir', '2ri', '2ii'], ['3rrr', '3irr', '3rir', '3iir', '3rri', '3iri', '3rii', '3iii']]
counter = 0
for file in files[dim - 1]: # For all the files
if os.path.exists(Dir + os.path.sep + file):
@@ -956,16 +1271,16 @@ def loadBrukerSpectrum(filePath):
if len(DATA) != 1:
hyper = np.array([0, 1])
if len(SIZE) == 2:
- for index in range(len(DATA)): # For each data set
+ for index, _ in enumerate(DATA): # For each data set
# Reshape DATA to 4D data using the block information
# Twice concat along axis 1 constructs the regular x-y data
- DATA[index] = np.reshape(DATA[index],[int(SIZE[1]/XDIM[1]),int(SIZE[0]/XDIM[0]),XDIM[1],XDIM[0]])
- DATA[index] = np.concatenate(np.concatenate(DATA[index],1),1)
+ DATA[index] = np.reshape(DATA[index], [int(SIZE[1]/XDIM[1]), int(SIZE[0]/XDIM[0]), XDIM[1], XDIM[0]])
+ DATA[index] = np.concatenate(np.concatenate(DATA[index], 1), 1)
elif len(SIZE) == 3:
- for index in range(len(DATA)):
+ for index, _ in enumerate(DATA):
# The same as 2D, but now split to 6D data, and concat along 2
- DATA[index] = np.reshape(DATA[index],[int(SIZE[2]/XDIM[2]),int(SIZE[1]/XDIM[1]),int(SIZE[0]/XDIM[0]),XDIM[2],XDIM[1],XDIM[0]])
- DATA[index] = np.concatenate(np.concatenate(np.concatenate(DATA[index],2),2),2)
+ DATA[index] = np.reshape(DATA[index], [int(SIZE[2]/XDIM[2]), int(SIZE[1]/XDIM[1]), int(SIZE[0]/XDIM[0]), XDIM[2], XDIM[1], XDIM[0]])
+ DATA[index] = np.concatenate(np.concatenate(np.concatenate(DATA[index], 2), 2), 2)
spec = [True]
masterData = sc.Spectrum(hc.HComplexData(DATA, hyper), (filePath, None), FREQ[-1::-1], SW[-1::-1], spec * dim, ref=REF[-1::-1])
masterData.addHistory("Bruker spectrum data loaded from " + filePath)
@@ -981,7 +1296,59 @@ def loadBrukerSpectrum(filePath):
pass #Do nothing on error
return masterData
+def loadBrukerImaging(filePath):
+ """
+ Load bruker topspin/paravision processed data.
+ Experimental at the moment.
+ """
+ if os.path.isfile(filePath):
+ Dir = os.path.dirname(filePath)
+ else:
+ Dir = filePath
+
+ File = 'd3proc'
+ if os.path.exists(Dir + os.path.sep + File):
+ Im_pars = brukerTopspinGetPars(Dir + os.path.sep + File)
+
+ pars = []
+ for File in ['procs', 'proc2s', 'proc3s']:
+ if os.path.exists(Dir + os.path.sep + File):
+ pars.append(brukerTopspinGetPars(Dir + os.path.sep + File))
+
+
+ SIZE = [Im_pars['IM_SIZ'], Im_pars['IM_SIY'], Im_pars['IM_SIX']]
+ FREQ = [0]*len(SIZE)
+ ByteOrder = ['l', 'b'][pars[0]['BYTORDP']] #The byte orders that is used
+ SPEC = [False,True,True]
+ SW = SIZE
+
+ totsize = np.prod(SIZE)
+
+ file = '2dseq'
+
+ with open(Dir + os.path.sep + file, "rb") as f:
+ raw = np.fromfile(f, np.int16, totsize)
+ raw = raw.newbyteorder(ByteOrder) # Set right byteorder
+# DATA = np.flipud(raw)
+
+ DATA = raw.reshape(SIZE)
+ masterData = sc.Spectrum(DATA, (filePath, None), FREQ, SW, SPEC)
+ return masterData
+
def chemGetPars(folder):
+ """
+ Loads Chemagentic parameter file.
+
+ Parameters
+ ----------
+ folder: string
+ Path to the folder that holds the files.
+
+ Returns
+ -------
+ dict:
+ Dictionary with all parameters
+ """
import collections
with open(folder + os.path.sep + 'acq', 'r') as f:
data = f.read().split('\n')
@@ -1014,12 +1381,25 @@ def convertChemVal(val):
elif val.endswith('us'):
num = float(val[:-2]) * 1e-6
elif val.endswith('s'):
- num = float(val[:-1])
+ num = float(val[:-1])
else:
num = float(val)
return num
def loadChemFile(filePath):
+ """
+ Loads Chemagentic data.
+
+ Parameters
+ ----------
+ filePath: string
+ Path to the file that should be loaded
+
+ Returns
+ -------
+ SpectrumClass
+ SpectrumClass object of the loaded data
+ """
if os.path.isfile(filePath):
Dir = os.path.dirname(filePath)
else:
@@ -1029,11 +1409,11 @@ def loadChemFile(filePath):
pars = chemGetPars(Dir)
sizeTD2 = int(float(pars['al']))
freq = pars['sf' + str(int(float(pars['ch1'])))]
- if type(freq) is list: #load only first value when list
+ if isinstance(freq, list): #load only first value when list
freq = float(freq[0])
else:
freq = float(freq)
- sw = 1 / convertChemVal(pars['dw'])
+ sw = 1 / convertChemVal(pars['dw'])
if any('array_num_values_' in s for s in pars):
if int(float(pars['use_array'])) == 1:
for s in pars:
@@ -1057,14 +1437,14 @@ def loadChemFile(filePath):
fid = np.reshape(fid, (len(fid)//sizeTD2, sizeTD2))
data = np.array(fid)
spec = [False]
- if sizeTD1 is 1:
+ if sizeTD1 == 1:
data = data[0][:]
masterData = sc.Spectrum(data, (filePath, None), [freq * 1e6], [sw], spec)
else:
masterData = sc.Spectrum(data, (filePath, None), [freq * 1e6] * 2, [sw1, sw], spec * 2)
masterData.addHistory("Chemagnetics data loaded from " + filePath)
try:
- if isinstance(pars['na'],list):
+ if isinstance(pars['na'], list):
masterData.metaData['# Scans'] = pars['na'][0]
else:
masterData.metaData['# Scans'] = pars['na']
@@ -1078,6 +1458,19 @@ def loadChemFile(filePath):
return masterData
def loadMagritek(filePath):
+ """
+ Loads Magritek data.
+
+ Parameters
+ ----------
+ filePath: string
+ Path to the file that should be loaded
+
+ Returns
+ -------
+ SpectrumClass
+ SpectrumClass object of the loaded data
+ """
# Magritek load script based on some Matlab files by Ole Brauckman
if os.path.isfile(filePath):
Dir = os.path.dirname(filePath)
@@ -1092,7 +1485,7 @@ def loadMagritek(filePath):
ref1 = None
# Start pars extraction
H = [line.strip().split('=') for line in open(Dir + os.path.sep + 'acqu.par', 'r')]
- H = [[x[0].strip(),x[1].strip()] for x in H]
+ H = [[x[0].strip(), x[1].strip()] for x in H]
H = dict(H)
sw = float(H['bandwidth']) * 1000
sizeTD2 = int(H['nrPnts'])
@@ -1115,9 +1508,9 @@ def loadMagritek(filePath):
Data = raw[-2 * sizeTD2 * sizeTD1::]
ComplexData = Data[0:Data.shape[0]:2] - 1j * Data[1:Data.shape[0]:2]
ComplexData = ComplexData.reshape((sizeTD1, sizeTD2))
- ComplexData[:,0] *= 2
+ ComplexData[:, 0] *= 2
masterData = sc.Spectrum(ComplexData, (filePath, None), [freq] * 2, [sw1, sw], [False] * 2, ref=[ref1, ref])
- elif len(Files1D) != 0:
+ elif Files1D:
File = 'data.1d'
with open(Dir + os.path.sep + File, 'rb') as f:
raw = np.fromfile(f, np.float32)
@@ -1137,6 +1530,17 @@ def loadMagritek(filePath):
return masterData
def saveSimpsonFile(filePath, spectrum):
+ """
+ Save to simpson format data. Only for 1D or 2D data. 2D data can be
+ either Spec-Spec, or FID-FID.
+
+ Parameters
+ ----------
+ filePath: string
+ Path of the file that should be saved
+ spectrum: SpectrumClass
+ The spectrum object to be saved
+ """
data = spectrum.getHyperData(0) # SIMPSON does not support hypercomplex
with open(filePath, 'w') as f:
f.write('SIMP\n')
@@ -1164,6 +1568,20 @@ def saveSimpsonFile(filePath, spectrum):
f.write('END')
def loadSimpsonFile(filePath):
+ """
+ Loads SIMPSON file. Both ASCII and binary data are supported. As well
+ as 1D and 2D data.
+
+ Parameters
+ ----------
+ filePath: string
+ Path to the file that should be loaded
+
+ Returns
+ -------
+ SpectrumClass
+ SpectrumClass object of the loaded data
+ """
with open(filePath, 'r') as f:
Lines = f.read().split('\n')
NP, NI, SW, SW1, TYPE, FORMAT = 0, 1, 0, 0, '', 'Normal'
@@ -1226,7 +1644,7 @@ def LAST(f, x): return ((x) & (~0 << (8 - f)))
spec = [False]
elif 'SPE' in TYPE:
spec = [True]
- if NI is 1:
+ if NI == 1:
masterData = sc.Spectrum(data, (filePath, None), [0], [SW], spec)
else:
masterData = sc.Spectrum(data, (filePath, None), [0, 0], [SW1, SW], spec * 2)
@@ -1234,6 +1652,19 @@ def LAST(f, x): return ((x) & (~0 << (8 - f)))
return masterData
def convertDIFDUB(dat):
+ """
+ Converts string of DIFDUB character encode to a array of floats
+
+ Parameters
+ ----------
+ dat: string
+ String with all the DIFDUB characters
+
+ Returns
+ -------
+ ndarray
+ 1-D array with the extracted numbers
+ """
def checkWrite(dup, currentNum, step, numberList):
if dup != '':
for dupli in range(int(dup)):
@@ -1281,10 +1712,22 @@ def checkWrite(dup, currentNum, step, numberList):
dup, currentNum, step, numberList = checkWrite(dup, currentNum, step, numberList)
if last:
return np.array(numberList)
- else:
- return np.array(numberList)[:-1]
+ return np.array(numberList)[:-1]
def loadJCAMP(filePath):
+ """
+ Loads JCAMP-DX file.
+
+ Parameters
+ ----------
+ filePath: string
+ Path to the file that should be loaded
+
+ Returns
+ -------
+ SpectrumClass
+ SpectrumClass object of the loaded data
+ """
with open(filePath, 'r') as f:
data = f.read().split('\n')
realDataPos = []
@@ -1327,7 +1770,7 @@ def loadJCAMP(filePath):
factor = re.sub(',[\t ][\t ]*', ' ', factor)
factor = re.sub('[\t\r]*', '', factor)
factor = factor.split()
- for elem in range(len(factor)):
+ for elem in enumerate(factor):
factor[elem] = float(factor[elem].replace(',', '.'))
elif '(X++(R..R))' in testline:
realDataPos.append(currentPos + 1)
@@ -1390,6 +1833,18 @@ def loadJCAMP(filePath):
return masterData
def saveASCIIFile(filePath, spectrum, axMult=1):
+ """
+ Save to ASCII format data.
+
+ Parameters
+ ----------
+ filePath: string
+ Path of the file that should be saved
+ spectrum: SpectrumClass
+ The spectrum object to be saved
+ axMult: float (optional)
+ Axis multiplier, needed to save in other unit than s or Hz
+ """
axis = np.array([spectrum.xaxArray[-1] * axMult]).transpose()
tmpData = spectrum.data.getHyperData(0)
if tmpData.ndim == 1: # create nx1 matrix if it is a 1d data set
@@ -1404,6 +1859,31 @@ def saveASCIIFile(filePath, spectrum, axMult=1):
np.savetxt(filePath, data, delimiter='\t')
def loadAscii(filePath, asciiInfo=None):
+ """
+ Loads general ASCII format data.
+
+ Parameters
+ ----------
+ filePath: string
+ Path to the file that should be loaded
+ asciiInfo: list
+ [dim, order, spec, delim, sw]
+ dim: int
+ Number of dimensions (1 or 2)
+ order: string
+ Data column description ('XRI','XR','XI','RI','R')
+ spec: bool
+ If True spectrum, otherwise FID
+ delim: string
+ Delimiter ('Tab','Space','Comma')
+ sw: float
+ Spectral width in kHz
+
+ Returns
+ -------
+ SpectrumClass
+ SpectrumClass object of the loaded data
+ """
if asciiInfo is None:
return
dataDimension = asciiInfo[0]
@@ -1465,6 +1945,19 @@ def loadAscii(filePath, asciiInfo=None):
return masterData
def loadMinispec(filePath):
+ """
+ Loads Bruker minispec data. The format is recognized by its .sig file.
+
+ Parameters
+ ----------
+ filePath: string
+ Path to the file that should be loaded
+
+ Returns
+ -------
+ SpectrumClass
+ SpectrumClass object of the loaded data
+ """
with open(filePath, 'r') as f:
data = f.read().split('\n')
dataType = int(data[1][data[1].index('=') + 1:])
@@ -1477,11 +1970,11 @@ def loadMinispec(filePath):
totaldata = np.array([])
if dataType == 1: # real data?
for line in data[7:]:
- if len(line) > 0:
+ if line:
totaldata = np.append(totaldata, float(line))
if dataType == 2: # Complex data
for line in data[7:]:
- if len(line) > 0:
+ if line:
temp = np.fromstring(line, sep='\t')
totaldata = np.append(totaldata, temp[0] + 1j * temp[1])
masterData = sc.Spectrum(totaldata, (filePath, None), [0], [sw], [False])
@@ -1489,6 +1982,22 @@ def loadMinispec(filePath):
return masterData
def loadBrukerEPR(filePath):
+ """
+ Loads Bruker EPR data. The format has both a .par and .spc file.
+ Note that ssNake at the moment only has s/Hz axes. In this case,
+ 1 Hz is the same as 1 Gauss.
+
+
+ Parameters
+ ----------
+ filePath: string
+ Path to the file that should be loaded
+
+ Returns
+ -------
+ SpectrumClass
+ SpectrumClass object of the loaded data
+ """
with open(filePath + '.par', mode='r') as f:
textdata = [row.split() for row in f.read().replace('\r', '\n').split('\n')]
for row in textdata:
@@ -1513,8 +2022,18 @@ def loadSiemensIMA(filePath):
Siemens specific fields. It's not a nice format to work with.
It is a combination of binary and text data. I, Vincent Breukels,
have little understanding in the file format. Rather it is a
- rewrite of the the following source: VeSPA, versatile simulation
+ rewrite of the following source: VeSPA, versatile simulation
pulses and analysis for magnetic resonance spectroscopy.
+
+ Parameters
+ ----------
+ filePath: string
+ Path to the file that should be loaded
+
+ Returns
+ -------
+ SpectrumClass
+ SpectrumClass object of the loaded data
"""
import struct
try:
@@ -1530,52 +2049,64 @@ def loadSiemensIMA(filePath):
# 'NumberOfFrames',)
relevantParameterFloats = ('RealDwellTime',
'ImagingFrequency')
- csaHeader = ds['0029','1110'].value
+ csaHeader = ds['0029', '1110'].value
# I assume all relevant header information I need is here. I have not yet
# encountered a file in which the relevant info. was in '0029','1120'[VB]
- if struct.unpack_from('8s',csaHeader,0)[0].decode() !='SV10\4\3\2\1' or struct.unpack_from('I',csaHeader,12)[0]!=77:
+ if struct.unpack_from('8s', csaHeader, 0)[0].decode() != 'SV10\4\3\2\1' or struct.unpack_from('I', csaHeader, 12)[0] != 77:
raise ValueError("IMA file not as expected: wrong first bytes")
- n_elems = struct.unpack_from('I',csaHeader,8)[0]
+ n_elems = struct.unpack_from('I', csaHeader, 8)[0]
currentIdx = 16
ParDict = {}
for i in range(n_elems):
- tagName = scrubber(struct.unpack_from('64s',csaHeader,currentIdx)[0].decode('utf-8','ignore'))
- n_items = struct.unpack_from('I',csaHeader,currentIdx + 76)[0]
- checkBit = struct.unpack_from('I',csaHeader,currentIdx + 80)[0]
+ tagName = scrubber(struct.unpack_from('64s', csaHeader, currentIdx)[0].decode('utf-8', 'ignore'))
+ n_items = struct.unpack_from('I', csaHeader, currentIdx + 76)[0]
+ checkBit = struct.unpack_from('I', csaHeader, currentIdx + 80)[0]
currentIdx += 84
- if checkBit not in [77,205]:
+ if checkBit not in (77, 205):
raise ValueError("IMA file not as expected: missing checkBit")
for idx in range(n_items):
- header = struct.unpack_from('4I',csaHeader,currentIdx)
- if (header[0]!=header[1]!=header[3]) or header[2] not in [77,205]:
+ header = struct.unpack_from('4I', csaHeader, currentIdx)
+ if (header[0] != header[1] != header[3]) or header[2] not in [77, 205]:
raise ValueError("IMA file does not seem to be correct")
length = header[0]
if idx == 0:
- data = struct.unpack_from('{0:d}s'.format(length),csaHeader,currentIdx + 16)[0]
+ data = struct.unpack_from('{0:d}s'.format(length), csaHeader, currentIdx + 16)[0]
currentIdx += int(np.ceil(length/4.) * 4) + 16
# Let's see if we got anything I want to keep:
if tagName in relevantParameterFloats:
- ParDict[tagName] = float(scrubber(data.decode('utf-8','ignore')))
+ ParDict[tagName] = float(scrubber(data.decode('utf-8', 'ignore')))
elif tagName in relevantParameterInts:
- ParDict[tagName] = int(scrubber(data.decode('utf-8','ignore')))
+ ParDict[tagName] = int(scrubber(data.decode('utf-8', 'ignore')))
# Statement below does not work in python 2.7, as struct_iter does not exist
#data = np.array([item[0]-1j*item[1] for item in struct.iter_unpack('2f',ds['7fe1','1010'].value)])
fmtString = str(ParDict['DataPointColumns'] * 2) + 'f'
- dataTuple = struct.unpack(fmtString,ds['7fe1','1010'].value)
- data = np.array(dataTuple[::2]) - 1j * np.array( dataTuple[1::2])
+ dataTuple = struct.unpack(fmtString, ds['7fe1', '1010'].value)
+ data = np.array(dataTuple[::2]) - 1j * np.array(dataTuple[1::2])
# First, I alway assume the data is in the tag 7fe1,1010. I haven't seen anything else
# Second, I don't understand the logic, but complex conjugate seems to be the correct ones
# I found this reshape shown below, possibly for 2d or 3d mrsi data, but i dont have an example data to test
# data.reshape((ParDict['DataPointColumns'],ParDict['Columns'],ParDict['Rows'],ParDict['NumberOfFrames']))
- sw = 1.0 / (ParDict['RealDwellTime'] * 1e-9)
+ sw = 1.0 / (ParDict['RealDwellTime'] * 1e-9)
freq = ParDict['ImagingFrequency'] * 1e6
masterData = sc.Spectrum(data, filePath, [freq], [sw])
masterData.addHistory("Siemens IMA data loaded from " + filePath)
return masterData
def scrubber(item):
- """Item is a string, scrubber returns the string up to the first \0 with
- leading/trailing whitespaces removed"""
+ """
+ Cleans the input string, returns the string up to the first \0 with
+ leading/trailing whitespaces removed
+
+ Parameters
+ ----------
+ item: string
+ The string that is to be cleaned
+
+ Returns
+ -------
+ string
+ Cleaned string
+ """
item = item.split(chr(0))[0]
return item.strip()
@@ -1583,43 +2114,50 @@ def scrubber(item):
def loadMestreC(filePath):
- import base64
- import xml.etree.ElementTree
- import re
+ """
+ Loads MestreC type data. MestreC data ends on .mrc, and is essentially XML data.
+ Parameters
+ ----------
+ filePath: string
+ Path to the file that should be loaded
+ Returns
+ -------
+ SpectrumClass
+ SpectrumClass object of the loaded data
+ """
+ import base64
+ import xml.etree.ElementTree
invalid_xml = re.compile(u'[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F]')
-
- with open(filePath,'r') as f:
+ with open(filePath, 'r') as f:
lines = f.read().split('\n')
parser = xml.etree.ElementTree.XMLParser()
for line in lines:
- line, count = invalid_xml.subn('', line)
+ line, _ = invalid_xml.subn('', line)
parser.feed(line)
main = parser.close().find('Spectrum').find('Main')
dim = int(main.find('Dimensions').text)
-
Points = main.find('Values').find('Points').text
data = base64.b64decode(Points)
data = np.fromstring(data, dtype='.
-import numpy as np
-import scipy.optimize
import copy
-from nus import ffm, clean, ist
import multiprocessing
import itertools
-import reimplement as reim
+import scipy.optimize
+import numpy as np
+import nus
import functions as func
import hypercomplex as hc
@@ -38,9 +37,58 @@ class SpectrumException(Exception):
# the generic spectrum class
-class Spectrum(object):
+class Spectrum:
+ """
+ The object that contains all relevant spectral information.
+ The functions for processing are methods of this object.
+ """
def __init__(self, data, filePath, freq, sw, spec=None, wholeEcho=None, ref=None, xaxArray=None, history=None, metaData=None, name='', dFilter=None):
+ """
+ Initializes the Spectrum object.
+
+ Parameters
+ ----------
+ data : HComplexData
+ The NMR data.
+ filePath : tuple
+ A tuple with the input parameters for the autoLoad function that was used to obtain this data.
+ freq : array_like
+ The frequency per dimension.
+ The list should have the same number of entries as the number of dimensions of data.
+ sw : array_like
+ The spectral width per dimension.
+ The list should have the same number of entries as the number of dimensions of data.
+ spec : array_like, optional
+ An array with booleans representing whether a dimension is in the frequency domain (True) or in the time domain (False).
+ The array should have the same number of entries as the number of dimensions of data.
+ By default all dimensions are set to time domain.
+ wholeEcho : array_like, optional
+ An array with booleans representing whether a dimension is recorded as a whole echo.
+ The array should have the same number of entries as the number of dimensions of data.
+ By default all dimensions are set to False.
+ ref : array_like, optional
+ The reference frequency per dimension.
+ The array should have the same number of entries as the number of dimensions of data.
+ By default the reference frequencies are set to None.
+ xaxArray : list of arrays, optional
+ The x-axis values per dimension.
+ The list should have the same number of entries as the number of dimensions of data.
+ By default the x-axes are generated based on the sw values.
+ history : list of strings, optional
+ The processing history of the data.
+ By default the history is set to an empty list.
+ metaData : dict, optional
+ Contains the metadata.
+ The dictionary contains the the keys ('# Scans', 'Acquisition Time [s]', 'Experiment Name','Receiver Gain', 'Recycle Delay [s]', 'Sample', 'Offset [Hz]', 'Time Completed').
+ By default all metadata is set to unknown.
+ name : str, optional
+ A string with the name of the spectrum.
+ By default the name is set to an empty string.
+ dFilter : float or None, optional
+ For a (Bruker) digital filter this value contains the first order phase correction required to correct for the digital filter.
+ By default this parameter is set to None.
+ """
self.name = name
if isinstance(data, hc.HComplexData):
self.data = data
@@ -49,7 +97,7 @@ def __init__(self, data, filePath, freq, sw, spec=None, wholeEcho=None, ref=None
self.filePath = filePath
self.freq = np.array(freq) # array of center frequency (length is dim, MHz)
self.sw = np.array(sw, dtype=float) # array of sweepwidths
- self.dFilter = dFilter #Digital filter first order phase in radian
+ self.dFilter = dFilter # Digital filter first order phase in radian
self.undoList = []
self.redoList = []
self.noUndo = False
@@ -75,8 +123,8 @@ def __init__(self, data, filePath, freq, sw, spec=None, wholeEcho=None, ref=None
else:
self.history = history
if metaData is None:
- self.metaData = {'# Scans': '-', 'Acquisition Time [s]': '-', 'Experiment Name': '-','Receiver Gain': '-', 'Recycle Delay [s]': '-',
- 'Sample': '-', 'Offset [Hz]': '-', 'Time Completed': '-'}
+ self.metaData = {'# Scans': '-', 'Acquisition Time [s]': '-', 'Experiment Name': '-', 'Receiver Gain': '-', 'Recycle Delay [s]': '-',
+ 'Sample': '-', 'Offset [Hz]': '-', 'Time Completed': '-'}
else:
self.metaData = metaData
@@ -86,7 +134,7 @@ def ndim(self):
def shape(self):
return self.data.shape()
- def getData(self): # Returns a copy of the data
+ def getData(self): # Returns a copy of the data
return copy.deepcopy(self.data)
def getHyperData(self, *args):
@@ -96,27 +144,80 @@ def isComplex(self, *args):
return self.data.isComplex(*args)
def rename(self, name):
+ """
+ Changes the name of the spectrum.
+
+ Parameters
+ ----------
+ name : str
+ The new name.
+ """
self.name = name
def getHistory(self):
+ """
+ Returns the history separated by newlines.
+ """
return "\n".join(self.history)
def addHistory(self, msg):
+ """
+ Adds a message to the data history.
+
+ Parameters
+ ----------
+ msg : str
+ The message to add to the history list.
+ """
self.history.append(msg)
def removeFromHistory(self, num=1):
+ """
+ Gives the history where a given number of messages have been removed from the end of the list.
+
+ Parameters
+ ----------
+ num : int
+ The number of entries to remove.
+
+ Returns
+ -------
+ list of str
+ The history list.
+ """
for i in range(num):
- if len(self.history) > 0:
+ if self.history:
val = self.history.pop()
return val
def setNoUndo(self, val):
+ """
+ Sets the "no undo" mode of the data.
+
+ Parameters
+ ----------
+ val : bool
+ When True, the undo and redo lists are cleared and the "no undo" mode is turned on.
+ """
self.noUndo = bool(val)
if self.noUndo:
self.undoList = []
self.redoList = []
def undo(self):
+ """
+ Undoes the last operation and puts it in the redo list.
+
+ Returns
+ -------
+ str
+ The undo message.
+
+ Raises
+ ------
+ SpectrumException
+ When the undo list is empty.
+ """
undoFunc = None
while undoFunc is None and self.undoList:
undoFunc = self.undoList.pop()
@@ -130,6 +231,14 @@ def undo(self):
return "Undo: " + message
def redo(self):
+ """
+ Redoes the last undo operation and puts it in the undo list.
+
+ Raises
+ ------
+ SpectrumException
+ When the redo list is empty.
+ """
if not self.redoList:
raise SpectrumException("No redo information")
tmpRedo = self.redoList # Protect the redo list
@@ -137,22 +246,56 @@ def redo(self):
self.redoList = tmpRedo # Restore the redo list
def clearUndo(self):
+ """
+ Clears the undo and redo lists.
+ """
self.undoList = []
self.redoList = []
def reload(self):
+ """
+ Reloads the data based on the filePath of this spectrum.
+ """
import specIO as io
loadData = io.autoLoad(*self.filePath)
self.restoreData(loadData, None)
-
+
def checkAxis(self, axis):
+ """
+ Checks whether a given axis is a valid index for this data.
+
+ Parameters
+ ----------
+ axis : int
+ The index to be tested.
+
+ Returns
+ -------
+ int
+ The index converted to a positive value.
+
+ Raises
+ ------
+ IndexError
+ When the axis is not valid.
+ """
if axis < 0:
axis += self.ndim()
- if not (0 <= axis < self.ndim()):
+ if not 0 <= axis < self.ndim():
raise IndexError("Not a valid axis for Spectrum")
return axis
def resetXax(self, axis=None):
+ """
+ Resets the x-axis based on the spectral width.
+
+ Parameters
+ ----------
+ axis : int or None, optional
+ The axis for which to reset the x-axis.
+ When None, all x-axes are reset.
+ By default axis is None.
+ """
if axis is not None:
axis = self.checkAxis(axis)
val = [axis]
@@ -167,6 +310,23 @@ def resetXax(self, axis=None):
self.xaxArray[i] += self.freq[i] - self.ref[i]
def setXax(self, xax, axis=-1):
+ """
+ Sets the x-axis of a given dimension.
+
+ Parameters
+ ----------
+ xax : array_like
+ The x-axis.
+ It should have the same length as the size of the data along dimension axis.
+ axis : int, optional
+ The dimension for which to set the x-axis.
+ By default the last axis is used.
+
+ Raises
+ ------
+ SpectrumException
+ When the length of xax does not match the length of the data
+ """
axis = self.checkAxis(axis)
if len(xax) != self.shape()[axis]:
raise SpectrumException("Length of new x-axis does not match length of the data")
@@ -178,6 +338,19 @@ def setXax(self, xax, axis=-1):
self.undoList.append(lambda self: self.setXax(oldXax, axis))
def insert(self, data, pos, axis=-1):
+ """
+ Insert data in a given position along a certain dimension.
+
+ Parameters
+ ----------
+ data : HComplexData or array_like
+ The data to insert.
+ pos : int
+ The index after which to add the data.
+ axis : int, optional
+ The dimension along which to add the data.
+ By default the last dimension is used.
+ """
if not isinstance(data, hc.HComplexData):
data = hc.HComplexData(data)
if self.noUndo:
@@ -198,6 +371,22 @@ def insert(self, data, pos, axis=-1):
self.undoList.append(returnValue)
def delete(self, pos, axis=-1):
+ """
+ Deletes a given range of indices of a certain dimension from the data.
+
+ Parameters
+ ----------
+ pos : int or array_like
+ The indices to remove.
+ axis : int, optional
+ The dimension along which to delete the data.
+ By default the last dimension is used.
+
+ Raises
+ ------
+ SpectrumException
+ When the deletion removes all data from a dimension.
+ """
axis = self.checkAxis(axis)
if not self.noUndo:
copyData = copy.deepcopy(self)
@@ -226,8 +415,23 @@ def __radd__(self, other):
def __iadd__(self, other):
self.add(other)
return self
-
+
def add(self, data, axis=None, select=slice(None)):
+ """
+ Adds given data to the spectrum data.
+ The addition follows the Numpy broadcasting rules.
+
+ Parameters
+ ----------
+ data : Spectrum, HComplexData or ndarray
+ The data to add.
+ axis : int, optional
+ The dimension along which to add the data.
+ By default the last dimension is used.
+ select : Slice, optional
+ An optional selection of the spectrum data on which the addition is performed.
+ By default the entire data is used.
+ """
if axis is not None:
axis = self.checkAxis(axis)
if isinstance(data, Spectrum):
@@ -246,7 +450,7 @@ def add(self, data, axis=None, select=slice(None)):
copyData = copy.deepcopy(self)
returnValue = lambda self: self.restoreData(copyData, lambda self: self.add(data, axis, select))
self.data[select] += data
- if isinstance(data, (float,int)):
+ if isinstance(data, (float, int)):
self.addHistory("Added " + str(data) + " to data[" + str(select) + "]")
else:
self.addHistory("Added to data[" + str(select) + "]")
@@ -265,8 +469,23 @@ def __rsub__(self, other):
def __isub__(self, other):
self.subtract(other)
return self
-
+
def subtract(self, data, axis=None, select=slice(None)):
+ """
+ Subtract given data from the spectrum data.
+ The subtraction follows the Numpy broadcasting rules.
+
+ Parameters
+ ----------
+ data : Spectrum, HComplexData or ndarray
+ The data to subtract.
+ axis : int, optional
+ The dimension along which to subtract the data.
+ By default the last dimension is used.
+ select : Slice, optional
+ An optional selection of the spectrum data on which the subtraction is performed.
+ By default the entire data is used.
+ """
if axis is not None:
axis = self.checkAxis(axis)
if isinstance(data, Spectrum):
@@ -285,7 +504,7 @@ def subtract(self, data, axis=None, select=slice(None)):
copyData = copy.deepcopy(self)
returnValue = lambda self: self.restoreData(copyData, lambda self: self.subtract(data, axis, select))
self.data[select] -= data
- if isinstance(data, (float,int)):
+ if isinstance(data, (float, int)):
self.addHistory("Subtracted " + str(data) + " from data[" + str(select) + "]")
else:
self.addHistory("Subtracted from data[" + str(select) + "]")
@@ -304,8 +523,23 @@ def __rmul__(self, other):
def __imul__(self, other):
self.multiply(other)
return self
-
+
def multiply(self, data, axis=None, select=slice(None)):
+ """
+ Multiply given data with the spectrum data.
+ The multiplication follows the Numpy broadcasting rules.
+
+ Parameters
+ ----------
+ data : Spectrum, HComplexData or ndarray
+ The data to multiply.
+ axis : int, optional
+ The dimension along which to multiply the data.
+ By default the last dimension is used.
+ select : Slice, optional
+ An optional selection of the spectrum data on which the multiplication is performed.
+ By default the entire data is used.
+ """
if axis is not None:
axis = self.checkAxis(axis)
if isinstance(data, Spectrum):
@@ -318,13 +552,13 @@ def multiply(self, data, axis=None, select=slice(None)):
if not self.noUndo:
if not isinstance(data, hc.HComplexData):
returnValue = lambda self: self.divide(data, axis, select=select)
- elif self.data.hyper == data.hyper: #If both sets have same hyper: easy subtract can be used for undo
+ elif self.data.hyper == data.hyper: # If both sets have same hyper: easy subtract can be used for undo
returnValue = lambda self: self.divide(data, axis, select=select)
else: # Otherwise: do a deep copy of the class
copyData = copy.deepcopy(self)
returnValue = lambda self: self.restoreData(copyData, lambda self: self.multiply(data, axis, select))
self.data[select] *= data
- if isinstance(data, (float,int)):
+ if isinstance(data, (float, int)):
self.addHistory("Multiplied data[" + str(select) + "] with " + str(data))
else:
self.addHistory("Multiplied data[" + str(select) + "]")
@@ -342,8 +576,23 @@ def __div__(self, other):
def __idiv__(self, other):
self.divide(self, other)
return self
-
+
def divide(self, data, axis=None, select=slice(None)):
+ """
+ Divide the spectrum data with the given data.
+ The division follows the Numpy broadcasting rules.
+
+ Parameters
+ ----------
+ data : Spectrum, HComplexData or ndarray
+ The data to divide with.
+ axis : int, optional
+ The dimension along which to divide the data.
+ By default the last dimension is used.
+ select : Slice, optional
+ An optional selection of the spectrum data on which the division is performed.
+ By default the entire data is used.
+ """
if axis is not None:
axis = self.checkAxis(axis)
if isinstance(data, Spectrum):
@@ -362,7 +611,7 @@ def divide(self, data, axis=None, select=slice(None)):
copyData = copy.deepcopy(self)
returnValue = lambda self: self.restoreData(copyData, lambda self: self.divide(data, axis, select))
self.data[select] /= data
- if isinstance(data, (float,int)):
+ if isinstance(data, (float, int)):
self.addHistory("Divided data[" + str(select) + "] with " + str(data))
else:
self.addHistory("Divided data[" + str(select) + "]")
@@ -371,9 +620,34 @@ def divide(self, data, axis=None, select=slice(None)):
self.undoList.append(returnValue)
def normalize(self, mult, scale=1.0, type=0, axis=-1, select=slice(None)):
+ """
+ Method used by the normalization.
+
+ Parameters
+ ----------
+ mult : float
+ The multiplier to normalize the data.
+ scale : float, optional
+ The scale to which to set the data.
+ By default the scale is 1.
+ type : int, optional
+ The type of normalization (0=integral, 1=maximum, 2=minimum, only used for the history message).
+ By default 0.
+ axis : int, optional
+ The dimension along which the normalization was performed.
+ By default the last dimension is used.
+ select : Slice, optional
+ An optional selection of the spectrum data on which the normalization was performed.
+ By default the entire data is used.
+
+ Raises
+ ------
+ SpectrumException
+ When the multiplication results in an error.
+ """
axis = self.checkAxis(axis)
try:
- self.data *= mult * scale
+ self.data *= mult * scale
except ValueError as error:
raise SpectrumException('Normalize: ' + str(error))
if type == 0:
@@ -387,11 +661,26 @@ def normalize(self, mult, scale=1.0, type=0, axis=-1, select=slice(None)):
self.undoList.append(lambda self: self.normalize(1.0 / mult, scale, type, axis, select=select))
def baselineCorrection(self, baseline, axis=-1, select=slice(None)):
+ """
+ Applies a baseline correction.
+
+ Parameters
+ ----------
+ baseline : array_like
+ The baseline to subtract.
+ It follows the Numpy broadcasting rules.
+ axis : int, optional
+ The dimension along which the baseline correction is performed.
+ By default the last dimension is used.
+ select : Slice, optional
+ An optional selection of the spectrum data on which the baseline correction is performed.
+ By default the entire data is used.
+ """
axis = self.checkAxis(axis)
baselinetmp = baseline.reshape((self.shape()[axis], ) + (1, ) * (self.ndim() - axis - 1))
self.data[select] -= baselinetmp
Message = "Baseline corrected dimension " + str(axis + 1)
- if type(select) is not slice:
+ if not isinstance(select, slice):
Message = Message + " with slice " + str(select)
elif select != slice(None, None, None):
Message = Message + " with slice " + str(select)
@@ -401,6 +690,15 @@ def baselineCorrection(self, baseline, axis=-1, select=slice(None)):
self.undoList.append(lambda self: self.baselineCorrection(-baseline, axis, select=select))
def concatenate(self, axis=-1):
+ """
+ Concatenates the data along a given dimension.
+
+ Parameters
+ ----------
+ axis : int, optional
+ The dimension along which to concatenate.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
splitVal = self.shape()[axis]
copyData = None
@@ -427,6 +725,18 @@ def concatenate(self, axis=-1):
self.undoList.append(lambda self: self.split(splitVal, axis))
def split(self, sections, axis=-1):
+ """
+ Splits the data into a given number of sections.
+
+ Parameters
+ ----------
+ sections : int
+ The number of sections.
+ The length of the data along axis should be divisible by this number.
+ axis : int, optional
+ The dimension along which to split.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
self.data = self.data.split(sections, axis)
self.data.insertDim(0)
@@ -444,6 +754,15 @@ def split(self, sections, axis=-1):
self.undoList.append(lambda self: self.concatenate(axis))
def real(self, axis=-1):
+ """
+ Sets the data to the real values along a given dimension.
+
+ Parameters
+ ----------
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
if not self.noUndo:
copyData = copy.deepcopy(self)
axis = self.checkAxis(axis)
@@ -454,6 +773,15 @@ def real(self, axis=-1):
self.undoList.append(lambda self: self.restoreData(copyData, lambda self: self.real(axis)))
def imag(self, axis=-1):
+ """
+ Sets the data to the imaginary values along a given dimension.
+
+ Parameters
+ ----------
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
if not self.noUndo:
copyData = copy.deepcopy(self)
axis = self.checkAxis(axis)
@@ -464,6 +792,15 @@ def imag(self, axis=-1):
self.undoList.append(lambda self: self.restoreData(copyData, lambda self: self.imag(axis)))
def abs(self, axis=-1):
+ """
+ Sets the data to the absolute values along a given dimension.
+
+ Parameters
+ ----------
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
if not self.noUndo:
copyData = copy.deepcopy(self)
axis = self.checkAxis(axis)
@@ -472,8 +809,17 @@ def abs(self, axis=-1):
self.redoList = []
if not self.noUndo:
self.undoList.append(lambda self: self.restoreData(copyData, lambda self: self.abs(axis)))
-
+
def conj(self, axis=-1):
+ """
+ Complex conjugates the data along a given dimension.
+
+ Parameters
+ ----------
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
self.data = self.data.conj(axis)
self.addHistory("Complex conjugate along" + str(axis+1))
self.redoList = []
@@ -481,6 +827,15 @@ def conj(self, axis=-1):
self.undoList.append(lambda self: self.conj(axis))
def states(self, axis=-1):
+ """
+ Converts the data to hypercomplex based on States acquisition along a given dimension.
+
+ Parameters
+ ----------
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
if not self.noUndo:
copyData = copy.deepcopy(self)
@@ -492,6 +847,15 @@ def states(self, axis=-1):
self.undoList.append(lambda self: self.restoreData(copyData, lambda self: self.states(axis)))
def statesTPPI(self, axis=-1):
+ """
+ Converts the data to hypercomplex based on States-TPPI acquisition along a given dimension.
+
+ Parameters
+ ----------
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
if not self.noUndo:
copyData = copy.deepcopy(self)
@@ -503,6 +867,15 @@ def statesTPPI(self, axis=-1):
self.undoList.append(lambda self: self.restoreData(copyData, lambda self: self.statesTPPI(axis)))
def echoAntiEcho(self, axis=-1):
+ """
+ Converts the data to hypercomplex based on echo/antiecho acquisition along a given dimension.
+
+ Parameters
+ ----------
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
if not self.noUndo:
copyData = copy.deepcopy(self)
@@ -514,14 +887,34 @@ def echoAntiEcho(self, axis=-1):
self.undoList.append(lambda self: self.restoreData(copyData, lambda self: self.echoAntiEcho(axis)))
def subtractAvg(self, pos1=None, pos2=None, axis=-1):
+ """
+ Subtracts the average values between given indices along a dimension.
+
+ Parameters
+ ----------
+ pos1 : int, optional
+ First index to determine the average.
+ 0 by default.
+ pos2 : int, optional
+ Second index to determine the average.
+ Length of the data along axis by default.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+
+ Raises
+ ------
+ SpectrumException
+ When pos1 or pos2 are invalid.
+ """
axis = self.checkAxis(axis)
if pos1 is None:
pos1 = 0
if pos2 is None:
pos2 = self.shape()[axis]
- if not (0 <= pos1 <= self.shape()[axis]):
+ if not 0 <= pos1 <= self.shape()[axis]:
raise SpectrumException("Indices not within range")
- if not (0 <= pos2 <= self.shape()[axis]):
+ if not 0 <= pos2 <= self.shape()[axis]:
raise SpectrumException("Indices not within range")
if pos1 == pos2:
raise SpectrumException("Indices cannot be equal")
@@ -536,6 +929,30 @@ def subtractAvg(self, pos1=None, pos2=None, axis=-1):
self.undoList.append(lambda self: self.add(averages))
def matrixManip(self, pos1=None, pos2=None, axis=-1, which=0):
+ """
+ Performs the matrix manipulation methods such as integrate, sum, average, maximum, minimum, maximum position, and minimum position.
+
+ Parameters
+ ----------
+ pos1 : int or array_like, optional
+ First index/indices of the matrix manipulation.
+ 0 by default.
+ pos2 : int or array_like, optional
+ Second index/indices of the matrix manipulation.
+ Should have the same length as pos1.
+ Length of the data along axis by default.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ which : int, optional
+ The type of matrix manipulation to perform (0=integrate, 1=max, 2=min, 3=maxpos, 4=minpos, 5=sum, 6=average).
+ 0 by default.
+
+ Raises
+ ------
+ SpectrumException
+ When pos1 and pos2 have unequal lengths or when they contain invalid indices.
+ """
axis = self.checkAxis(axis)
if pos1 is None:
pos1 = 0
@@ -547,17 +964,14 @@ def matrixManip(self, pos1=None, pos2=None, axis=-1, which=0):
if len(pos1) != len(pos2):
raise SpectrumException("Length of the two arrays is not equal")
if len(pos1) == 1:
- if self.ndim() == 1:
- keepdims = True
- else:
- keepdims = False
+ keepdims = self.ndim() == 1
else:
keepdims = True
tmpdata = ()
- for i in range(len(pos1)):
- if not (0 <= pos1[i] <= self.shape()[axis]):
+ for i, _ in enumerate(pos1):
+ if not 0 <= pos1[i] <= self.shape()[axis]:
raise SpectrumException("Indices not within range")
- if not (0 <= pos2[i] <= self.shape()[axis]):
+ if not 0 <= pos2[i] <= self.shape()[axis]:
raise SpectrumException("Indices not within range")
if pos1[i] == pos2[i]:
raise SpectrumException("Indices cannot be equal")
@@ -611,6 +1025,22 @@ def matrixManip(self, pos1=None, pos2=None, axis=-1, which=0):
self.resetXax(axis)
def integrate(self, pos1=None, pos2=None, axis=-1):
+ """
+ Reduce the data to the integrals between given indices.
+
+ Parameters
+ ----------
+ pos1 : array_like, optional
+ First indices to determine the integrals.
+ 0 by default.
+ pos2 : array_like, optional
+ Second indices to determine the integrals.
+ Should have the same length as pos1.
+ Length of the data along axis by default.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
if not self.noUndo:
copyData = copy.deepcopy(self)
@@ -621,6 +1051,22 @@ def integrate(self, pos1=None, pos2=None, axis=-1):
self.addHistory("Integrate between " + str(pos1) + " and " + str(pos2) + " of dimension " + str(axis + 1))
def max(self, pos1=None, pos2=None, axis=-1):
+ """
+ Reduce the data to the maxima between given indices.
+
+ Parameters
+ ----------
+ pos1 : array_like, optional
+ First indices to determine the maxima.
+ 0 by default.
+ pos2 : array_like, optional
+ Second indices to determine the maxima.
+ Should have the same length as pos1.
+ Length of the data along axis by default.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
if not self.noUndo:
copyData = copy.deepcopy(self)
@@ -631,6 +1077,22 @@ def max(self, pos1=None, pos2=None, axis=-1):
self.addHistory("Maximum between " + str(pos1) + " and " + str(pos2) + " of dimension " + str(axis + 1))
def min(self, pos1=None, pos2=None, axis=-1):
+ """
+ Reduce the data to the minima between given indices.
+
+ Parameters
+ ----------
+ pos1 : array_like, optional
+ First indices to determine the minima.
+ 0 by default.
+ pos2 : array_like, optional
+ Second indices to determine the minima.
+ Should have the same length as pos1.
+ Length of the data along axis by default.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
if not self.noUndo:
copyData = copy.deepcopy(self)
@@ -641,6 +1103,22 @@ def min(self, pos1=None, pos2=None, axis=-1):
self.addHistory("Minimum between " + str(pos1) + " and " + str(pos2) + " of dimension " + str(axis + 1))
def argmax(self, pos1=None, pos2=None, axis=-1):
+ """
+ Reduce the data to the maxima positions between given indices.
+
+ Parameters
+ ----------
+ pos1 : array_like, optional
+ First indices to determine the maxima positions.
+ 0 by default.
+ pos2 : array_like, optional
+ Second indices to determine the maxima positions.
+ Should have the same length as pos1.
+ Length of the data along axis by default.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
if not self.noUndo:
copyData = copy.deepcopy(self)
@@ -651,6 +1129,22 @@ def argmax(self, pos1=None, pos2=None, axis=-1):
self.addHistory("Maximum position between " + str(pos1) + " and " + str(pos2) + " of dimension " + str(axis + 1))
def argmin(self, pos1=None, pos2=None, axis=-1):
+ """
+ Reduce the data to the minima positions between given indices.
+
+ Parameters
+ ----------
+ pos1 : array_like, optional
+ First indices to determine the minima positions.
+ 0 by default.
+ pos2 : array_like, optional
+ Second indices to determine the minima positions.
+ Should have the same length as pos1.
+ Length of the data along axis by default.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
if not self.noUndo:
copyData = copy.deepcopy(self)
@@ -661,6 +1155,22 @@ def argmin(self, pos1=None, pos2=None, axis=-1):
self.addHistory("Minimum position between " + str(pos1) + " and " + str(pos2) + " of dimension " + str(axis + 1))
def sum(self, pos1=None, pos2=None, axis=-1):
+ """
+ Reduce the data to the sum between given indices.
+
+ Parameters
+ ----------
+ pos1 : array_like, optional
+ First indices to determine the sum.
+ 0 by default.
+ pos2 : array_like, optional
+ Second indices to determine the sum.
+ Should have the same length as pos1.
+ Length of the data along axis by default.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
if not self.noUndo:
copyData = copy.deepcopy(self)
@@ -671,6 +1181,22 @@ def sum(self, pos1=None, pos2=None, axis=-1):
self.addHistory("Sum between " + str(pos1) + " and " + str(pos2) + " of dimension " + str(axis + 1))
def average(self, pos1=None, pos2=None, axis=-1):
+ """
+ Reduce the data to the average between given indices.
+
+ Parameters
+ ----------
+ pos1 : array_like, optional
+ First indices to determine the average.
+ 0 by default.
+ pos2 : array_like, optional
+ Second indices to determine the average.
+ Should have the same length as pos1.
+ Length of the data along axis by default.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
if not self.noUndo:
copyData = copy.deepcopy(self)
@@ -681,6 +1207,21 @@ def average(self, pos1=None, pos2=None, axis=-1):
self.addHistory("Average between " + str(pos1) + " and " + str(pos2) + " of dimension " + str(axis + 1))
def extract(self, pos1=None, pos2=None, axis=-1):
+ """
+ Extract the data between two given indices along a dimension and make it the new data.
+
+ Parameters
+ ----------
+ pos1 : int, optional
+ First index to extract.
+ 0 by default.
+ pos2 : int, optional
+ Second index to extract.
+ Length of the data along axis by default.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
if pos1 is None:
pos1 = 0
@@ -707,6 +1248,25 @@ def extract(self, pos1=None, pos2=None, axis=-1):
self.undoList.append(lambda self: self.restoreData(copyData, lambda self: self.extract(pos1, pos2, axis)))
def fiddle(self, refSpec, lb, axis=-1):
+ """
+ Performs reference deconvolution using the FIDDLE algorithm.
+
+ Parameters
+ ----------
+ refSpec : array_like
+ The reference spectrum with which to deconvolute the spectrum.
+ Should have the same length as the data along axis.
+ lb : float
+ The linebroadening (in Hz) to be applied during reference deconvolution.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+
+ Raises
+ ------
+ SpectrumException
+ When the reference FID does not have the same length as the data along axis.
+ """
axis = self.checkAxis(axis)
axLen = self.shape()[axis]
if len(refSpec) != axLen:
@@ -740,6 +1300,15 @@ def fiddle(self, refSpec, lb, axis=-1):
self.undoList.append(lambda self: self.restoreData(copyData, lambda self: self.fiddle(refSpec, lb, axis)))
def diff(self, axis=-1):
+ """
+ The discrete difference along a given dimension.
+
+ Parameters
+ ----------
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
if not self.noUndo:
copyData = copy.deepcopy(self)
@@ -751,6 +1320,15 @@ def diff(self, axis=-1):
self.undoList.append(lambda self: self.restoreData(copyData, lambda self: self.diff(axis)))
def cumsum(self, axis=-1):
+ """
+ The cumulative sum along a given dimension.
+
+ Parameters
+ ----------
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
if not self.noUndo:
copyData = copy.deepcopy(self)
@@ -761,6 +1339,15 @@ def cumsum(self, axis=-1):
self.undoList.append(lambda self: self.restoreData(copyData, lambda self: self.cumsum(axis)))
def flipLR(self, axis=-1):
+ """
+ Flips the data along a given dimension.
+
+ Parameters
+ ----------
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
slicing = (slice(None), ) * axis + (slice(None, None, -1), )
self.data = self.data[slicing]
@@ -770,6 +1357,15 @@ def flipLR(self, axis=-1):
self.undoList.append(lambda self: self.flipLR(axis))
def hilbert(self, axis=-1):
+ """
+ Performs a Hilbert transform along a given dimension.
+
+ Parameters
+ ----------
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
if not self.noUndo:
copyData = copy.deepcopy(self)
@@ -782,6 +1378,19 @@ def hilbert(self, axis=-1):
self.undoList.append(lambda self: self.restoreData(copyData, lambda self: self.hilbert(axis)))
def autoPhaseAll(self, phaseNum=0, axis=-1):
+ """
+ Autophases all traces along a given axis individually.
+
+ Parameters
+ ----------
+ phaseNum : {0, 1}, optional
+ Order up to which to perform the autophasing.
+ For 0 only zero order phasing is performed, for 1 both zero and first order phasing is performed.
+ 0 by default.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
if not self.noUndo:
copyData = copy.deepcopy(self)
@@ -790,7 +1399,7 @@ def autoPhaseAll(self, phaseNum=0, axis=-1):
rangeList = [range(i) for i in shape]
for i in itertools.product(*rangeList):
locList = np.insert(i, axis, 0)
- selectList = np.insert(np.array(i,dtype=object), axis, slice(None))
+ selectList = np.insert(np.array(i, dtype=object), axis, slice(None))
self.autoPhase(phaseNum, axis, locList, False, selectList)
if phaseNum == 1:
self.addHistory("Autophased per trace for 0 + 1 order along axis " + str(axis + 1))
@@ -801,6 +1410,33 @@ def autoPhaseAll(self, phaseNum=0, axis=-1):
self.undoList.append(lambda self: self.restoreData(copyData, lambda self: self.autoPhaseAll(phaseNum, axis)))
def autoPhase(self, phaseNum=0, axis=-1, locList=None, returnPhases=False, select=slice(None)):
+ """
+ Autophases a spectrum.
+
+ Parameters
+ ----------
+ phaseNum : {0, 1}, optional
+ Order up to which to perform the autophasing.
+ For 0 only zero order phasing is performed, for 1 both zero and first order phasing is performed.
+ 0 by default.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ locList : array_like of int, optional
+ The indices of the trace to determine the phase values.
+ By default the first index of each dimension is used.
+ returnPhases : bool, optional
+ If True the determined phases are return.
+ False by default.
+ select : Slice, optional
+ An optional selection of the spectrum data on which the phasing is performed.
+ By default the entire data is used.
+
+ Raises
+ ------
+ SpectrumException
+ When locList does not have the same length as the number of dimensions or when locList contains invalid indices.
+ """
axis = self.checkAxis(axis)
if locList is None:
locList = [0]*self.ndim()
@@ -814,15 +1450,14 @@ def autoPhase(self, phaseNum=0, axis=-1, locList=None, returnPhases=False, selec
if self.spec[axis] == 0:
self.__fourier(axis, tmp=True)
tmp = self.data[locList]
- tmp = tmp.getHyperData(0)
+ tmp = tmp.getHyperData(0) # only optimize on the hyper real data
x = np.fft.fftshift(np.fft.fftfreq(len(tmp), 1.0 / self.sw[axis])) / self.sw[axis]
- # only optimize on the hyper real data
if phaseNum == 0:
- phases = scipy.optimize.minimize(self.ACMEentropy, [0], (tmp, x, False), method='Powell',options = {'xtol': AUTOPHASETOL})
+ phases = scipy.optimize.minimize(func.ACMEentropy, [0], (tmp, x, False), method='Powell', options={'xtol': AUTOPHASETOL})
phase0 = phases['x']
phase1 = 0.0
elif phaseNum == 1:
- phases = scipy.optimize.minimize(self.ACMEentropy, [0, 0], (tmp, x), method='Powell', options = {'xtol': AUTOPHASETOL})
+ phases = scipy.optimize.minimize(func.ACMEentropy, [0, 0], (tmp, x), method='Powell', options={'xtol': AUTOPHASETOL})
phase0 = phases['x'][0]
phase1 = phases['x'][1]
if self.ref[axis] is None:
@@ -840,33 +1475,11 @@ def autoPhase(self, phaseNum=0, axis=-1, locList=None, returnPhases=False, selec
if returnPhases:
if phaseNum == 0:
return [phases['x']]
- else:
- return phases['x']
+ return phases['x']
self.redoList = []
if not self.noUndo:
self.undoList.append(lambda self: self.phase(-phase0, -phase1, axis))
- def ACMEentropy(self, phaseIn, data, x, phaseAll=True):
- phase0 = phaseIn[0]
- if phaseAll:
- phase1 = phaseIn[1]
- else:
- phase1 = 0.0
- L = len(data)
- s0 = data * np.exp(1j * (phase0 + phase1 * x))
- s2 = np.real(s0)
- ds1 = np.abs((s2[3:L] - s2[1:L - 2]) / 2.0)
- p1 = ds1 / sum(ds1)
- p1[np.where(p1 == 0)] = 1
- h1 = -p1 * np.log(p1)
- H1 = sum(h1)
- Pfun = 0.0
- as1 = s2 - np.abs(s2)
- sumas = sum(as1)
- if (np.real(sumas) < 0):
- Pfun = Pfun + sum(as1**2) / 4 / L**2
- return H1 + 1000 * Pfun
-
def __phase(self, phase0, phase1, offset, axis, select=slice(None)):
vector = np.exp(np.fft.fftshift(np.fft.fftfreq(self.shape()[axis], 1.0 / self.sw[axis]) + offset) / self.sw[axis] * phase1 * 1j)
if self.spec[axis] == 0:
@@ -878,34 +1491,103 @@ def __phase(self, phase0, phase1, offset, axis, select=slice(None)):
if self.spec[axis] == 0:
self.__invFourier(axis, tmp=True)
- def phase(self, phase0=0.0, phase1=0.0, axis=-1, select=slice(None), internal = False):
+ def phase(self, phase0=0.0, phase1=0.0, axis=-1, select=slice(None)):
+ """
+ Phases a spectrum along a given dimension.
+
+ Parameters
+ ----------
+ phase0 : float, optional
+ Zero order phase.
+ 0.0 by default.
+ phase1 : float, optional
+ First order phase.
+ 0.0 by default.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ select : Slice, optional
+ An optional selection of the spectrum data on which the phasing is performed.
+ By default the entire data is used.
+ """
axis = self.checkAxis(axis)
if self.ref[axis] is None:
offset = 0
else:
offset = self.freq[axis] - self.ref[axis]
self.__phase(phase0, phase1, offset, axis, select=select)
- if not internal:
- Message = "Phasing: phase0 = " + str(phase0 * 180 / np.pi) + " and phase1 = " + str(phase1 * 180 / np.pi) + " for dimension " + str(axis + 1)
- if type(select) is not slice:
- Message = Message + " with slice " + str(select)
- elif select != slice(None, None, None):
- Message = Message + " with slice " + str(select)
- self.addHistory(Message)
- self.redoList = []
- if not self.noUndo:
- self.undoList.append(lambda self: self.phase(-phase0, -phase1, axis, select=select))
+ Message = "Phasing: phase0 = " + str(phase0 * 180 / np.pi) + " and phase1 = " + str(phase1 * 180 / np.pi) + " for dimension " + str(axis + 1)
+ if not isinstance(select, slice):
+ Message = Message + " with slice " + str(select)
+ elif select != slice(None, None, None):
+ Message = Message + " with slice " + str(select)
+ self.addHistory(Message)
+ self.redoList = []
+ if not self.noUndo:
+ self.undoList.append(lambda self: self.phase(-phase0, -phase1, axis, select=select))
+
+ def correctDFilter(self, axis=-1):
+ """
+ Corrects the digital filter via first order phasing along a given dimension.
- def correctDFilter(self, axis=-1, undo = False):
- #Corrects the digital filter via first order phasing
- self.phase(0,self.dFilter,axis,internal = True)
+ Parameters
+ ----------
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
+ axis = self.checkAxis(axis)
+ if self.ref[axis] is None:
+ offset = 0
+ else:
+ offset = self.freq[axis] - self.ref[axis]
+ self.__phase(0, self.dFilter, offset, axis)
Message = "Corrected digital filter"
self.addHistory(Message)
self.redoList = []
if not self.noUndo:
- self.undoList.append(lambda self: self.phase(0,-self.dFilter,axis,internal = False,))
+ self.undoList.append(lambda self: self.phase(0, -self.dFilter, offset, axis))
def apodize(self, lor=None, gauss=None, cos2=[None, None], hamming=None, shift=0.0, shifting=0.0, shiftingAxis=None, axis=-1, select=slice(None), preview=False):
+ """
+ Apodizes an FID or spectrum along a given dimension.
+
+ Parameters
+ ----------
+ lor : float, optional
+ The Lorentzian component of the apodization window.
+ By default Lorentzian apodization is not applied.
+ gauss : float, optional
+ The Gaussian component of the apodization window.
+ By default Gaussian apodization is not applied.
+ cos2 : array_like, optional
+ Defines the squared cosine apodization component.
+ Should have a length of at least two.
+ The first value is the frequency (two times the number of periods in the time domain).
+ The second value is the phase shift in degrees.
+ By default squared cosine apodization is not applied.
+ hamming : float, optional
+ The Hamming window component.
+ By default Hamming apodization is not applied.
+ shift : float, optional
+ A shift in time of the function.
+ A positive value shift the curve to later times.
+ By default a shift of 0.0 is used.
+ shifting : float, optional
+ A shift in time of the function as a function of the x-axis values along shiftingAxis.
+ A positive value shift the curve to later times.
+ By default a shifting of 0.0 is used.
+ shiftingAxis : int, optional
+ The dimension for the shifting.
+ If this parameter is None, no shifting is applied.
+ By default shifting is not used.
+ axis : int, optional
+ The dimension along which the apodization is applied.
+ By default the last dimension is used.
+ select : Slice, optional
+ An optional selection of the spectrum data on which the apodization is performed.
+ By default the entire data is used.
+ """
axis = self.checkAxis(axis)
if shiftingAxis is None:
shiftingAxis = 0
@@ -919,7 +1601,7 @@ def apodize(self, lor=None, gauss=None, cos2=[None, None], hamming=None, shift=0
shift1 = shift + shifting * np.arange(self.shape()[shiftingAxis]) / self.sw[shiftingAxis]
else:
shift1 = shift + shifting * self.xaxArray[shiftingAxis]
- previewData = np.array([func.apodize(t, s, self.sw[axis], axLen, lor, gauss, cos2, hamming, self.wholeEcho[axis]) for s in shift1])
+ previewData = np.array([func.apodize(t, s, lor, gauss, cos2, hamming, self.wholeEcho[axis]) for s in shift1])
if axis < shiftingAxis:
previewData = np.swapaxis(previewData, 0, 1)
multShape = np.ones(len(self.shape()), dtype=int)
@@ -937,7 +1619,7 @@ def apodize(self, lor=None, gauss=None, cos2=[None, None], hamming=None, shift=0
if self.spec[axis] > 0:
self.__fourier(axis, tmp=True)
else:
- x = func.apodize(t, shift, self.sw[axis], axLen, lor, gauss, cos2, hamming, self.wholeEcho[axis])
+ x = func.apodize(t, shift, lor, gauss, cos2, hamming, self.wholeEcho[axis])
if preview:
previewData = [x] * int(np.prod(self.data.shape()) / self.data.shape()[axis])
if self.spec[axis] > 0:
@@ -966,7 +1648,7 @@ def apodize(self, lor=None, gauss=None, cos2=[None, None], hamming=None, shift=0
if lor is None and gauss is None and cos2 is None and hamming is None: # If all none, make special message with `zero apodization'
Message = Message + "zero apodization"
Message = Message + " for dimension " + str(axis + 1)
- if type(select) is not slice:
+ if not isinstance(select, slice):
Message = Message + " with slice " + str(select)
elif select != slice(None, None, None):
Message = Message + " with slice " + str(select)
@@ -978,6 +1660,21 @@ def apodize(self, lor=None, gauss=None, cos2=[None, None], hamming=None, shift=0
self.undoList.append(lambda self: self.restoreData(copyData, lambda self: self.apodize(lor, gauss, cos2, hamming, shift, shifting, shiftingAxis, axis, select=select)))
def setFreq(self, freq=None, sw=None, axis=-1):
+ """
+ Sets the frequency or spectral width of a certain dimension to a given value.
+
+ Parameters
+ ----------
+ freq : float, optional
+ The new frequency of axis in Hz
+ By default the frequency is unchanged.
+ sw : float, optional
+ The new spectral width of axis in Hz.
+ By default the spectral width is unchanged.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
oldFreq = self.freq[axis]
oldSw = self.sw[axis]
@@ -994,6 +1691,17 @@ def setFreq(self, freq=None, sw=None, axis=-1):
self.undoList.append(lambda self: self.setFreq(oldFreq, oldSw, axis))
def scaleSw(self, scale, axis=-1):
+ """
+ Scales the spectral with of a dimension by a given scaling factor.
+
+ Parameters
+ ----------
+ scale : float
+ The scaling factor.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
oldSw = self.sw[axis]
self.sw[axis] = float(scale) * oldSw
@@ -1004,6 +1712,19 @@ def scaleSw(self, scale, axis=-1):
self.undoList.append(lambda self: self.scaleSw(1.0 / scale, axis))
def setRef(self, ref=None, axis=-1):
+ """
+ Sets the reference frequency to a given value.
+
+ Parameters
+ ----------
+ ref : float or None, optional
+ The reference frequency in Hz.
+ If None, the reference is removed.
+ None by default.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
oldRef = self.ref[axis]
if ref is None:
@@ -1018,7 +1739,19 @@ def setRef(self, ref=None, axis=-1):
self.undoList.append(lambda self: self.setRef(oldRef, axis))
def regrid(self, limits, numPoints, axis=-1):
- oldLimits = [self.xaxArray[axis][0], self.xaxArray[axis][-1]]
+ """
+ Regrids the data along a dimension to match a given number of points.
+
+ Parameters
+ ----------
+ limits : list of float
+ The left and right limit of the new x-axis for the regrid.
+ numPoints : int
+ The number of points the data should have after the regrid.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
if not self.noUndo:
copyData = copy.deepcopy(self)
newSw = (limits[1] - limits[0]) / (numPoints - 1) * numPoints
@@ -1041,6 +1774,17 @@ def regrid(self, limits, numPoints, axis=-1):
self.undoList.append(lambda self: self.restoreData(copyData, lambda self: self.regrid(limits, numPoints, axis)))
def setWholeEcho(self, val, axis=-1):
+ """
+ Sets the Whole Echo attribute for a given dimension.
+
+ Parameters
+ ----------
+ val : bool
+ The new Whole Echo setting.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
self.wholeEcho[axis] = val
self.addHistory("Whole echo set to " + str(val) + " for dimension " + str(axis + 1))
@@ -1049,6 +1793,19 @@ def setWholeEcho(self, val, axis=-1):
self.undoList.append(lambda self: self.setWholeEcho(not val, axis))
def resize(self, size, pos, axis=-1):
+ """
+ Resizes the data along a dimension by zerofilling in the time domain.
+
+ Parameters
+ ----------
+ size : int
+ The new size along axis.
+ pos : int
+ The index after which the zeros are added in the time domain.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
if not self.noUndo:
copyData = copy.deepcopy(self)
@@ -1064,6 +1821,31 @@ def resize(self, size, pos, axis=-1):
self.undoList.append(lambda self: self.restoreData(copyData, lambda self: self.resize(size, pos, axis)))
def lpsvd(self, nPredict, maxFreq, forward=False, numPoints=None, axis=-1):
+ """
+ Performs linear prediction using the LPSVD algorithm.
+
+ Parameters
+ ----------
+ nPredict : int
+ The number of datapoints to predict.
+ maxFreq : int
+ The maximum number of frequencies to take from the SVD.
+ forward : bool, optional
+ If True, a forward prediction is performed, otherwise a backward prediction is performed.
+ False by default.
+ numPoints : int, optional
+ The number of points to use for SVD.
+ For efficiency this number can be reduced.
+ By default the entire data is used.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+
+ Raises
+ ------
+ SpectrumException
+ When the LPSVD algorithm resulted in an error.
+ """
failed = False
axis = self.checkAxis(axis)
if not self.noUndo:
@@ -1090,6 +1872,18 @@ def lpsvd(self, nPredict, maxFreq, forward=False, numPoints=None, axis=-1):
self.undoList.append(lambda self: self.restoreData(copyData, lambda self: self.lpsvd(nPredict, maxFreq, forward, numPoints, axis)))
def setSpec(self, val, axis=-1):
+ """
+ Sets the spectrum flag for a given dimension.
+
+ Parameters
+ ----------
+ val : bool
+ If True, the dimension is treated as a spectral domain.
+ If False, the dimension is treated as a time domain.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
oldVal = self.spec[axis]
self.spec[axis] = val
@@ -1103,6 +1897,17 @@ def setSpec(self, val, axis=-1):
self.undoList.append(lambda self: self.setSpec(oldVal, axis))
def swapEcho(self, idx, axis=-1):
+ """
+ Swaps an echo signal over a given index.
+
+ Parameters
+ ----------
+ idx : int
+ The index over which the data is swapped.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
slicing1 = (slice(None), ) * axis + (slice(None, idx), )
slicing2 = (slice(None), ) * axis + (slice(idx, None), )
@@ -1113,7 +1918,21 @@ def swapEcho(self, idx, axis=-1):
if not self.noUndo:
self.undoList.append(lambda self: self.swapEcho(-idx, axis))
- def shift(self, shift, axis=-1, select=slice(None), zeros=True):
+ def shift(self, shift, axis=-1, select=slice(None)):
+ """
+ Shifts the data a given number of datapoints.
+
+ Parameters
+ ----------
+ shift : int
+ The number of datapoints to shift.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ select : Slice, optional
+ An optional selection of the spectrum data on which the shift is performed.
+ By default the entire data is used.
+ """
axis = self.checkAxis(axis)
if not self.noUndo:
copyData = copy.deepcopy(self)
@@ -1125,21 +1944,35 @@ def shift(self, shift, axis=-1, select=slice(None), zeros=True):
else:
mask[slice(None, shift)] = 0
self.data[select] = self.data.roll(shift, axis)[select]
- if zeros:
- self.data[select] *= mask.reshape(mask.shape + (1,)*(self.ndim()-axis-1))
+ self.data[select] *= mask.reshape(mask.shape + (1,)*(self.ndim()-axis-1))
if self.spec[axis] > 0:
self.__fourier(axis, tmp=True)
Message = "Shifted " + str(shift) + " points in dimension " + str(axis + 1)
- if type(select) is not slice:
+ if not isinstance(select, slice):
Message = Message + " with slice " + str(select)
elif select != slice(None, None, None):
Message = Message + " with slice " + str(select)
self.addHistory(Message)
self.redoList = []
if not self.noUndo:
- self.undoList.append(lambda self: self.restoreData(copyData, lambda self: self.shift(shift, axis, select=select, zeros=zeros)))
+ self.undoList.append(lambda self: self.restoreData(copyData, lambda self: self.shift(shift, axis, select=select)))
def roll(self, shift, axis=-1, select=slice(None)):
+ """
+ Rolls the data by using a first order phase change.
+ This allows rolling also using non-integer values.
+
+ Parameters
+ ----------
+ roll : float
+ The distance to roll the data along axis.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ select : Slice, optional
+ An optional selection of the spectrum data on which the shift is performed.
+ By default the entire data is used.
+ """
axis = self.checkAxis(axis)
if self.spec[axis] == 0:
self.__phase(0, -2 * np.pi * shift, 0, axis, select=select)
@@ -1149,20 +1982,38 @@ def roll(self, shift, axis=-1, select=slice(None)):
self.__invFourier(axis, tmp=True)
t = t.reshape(t.shape + (1, )*(self.ndim()-axis-1))
self.data.icomplexReorder(axis)
- self.data[select] *= np.exp( - 1j * t * freq * shift * 2 * np.pi)
+ self.data[select] *= np.exp(-1j * t * freq * shift * 2 * np.pi)
self.data.icomplexReorder(axis)
self.__fourier(axis, tmp=True)
Message = "Rolled " + str(shift) + " points in dimension " + str(axis + 1)
- if type(select) is not slice:
+ if not isinstance(select, slice):
Message = Message + " with slice " + str(select)
elif select != slice(None, None, None):
Message = Message + " with slice " + str(select)
self.addHistory(Message)
self.redoList = []
if not self.noUndo:
- self.undoList.append(lambda self: self.roll(-shift,axis))
+ self.undoList.append(lambda self: self.roll(-shift, axis))
def align(self, pos1=None, pos2=None, axis=-1):
+ """
+ Aligns the maxima between given indices along a certain dimension.
+
+ Parameters
+ ----------
+ pos1 : int
+ The first index between which to determine the maximum.
+ pos2 : int
+ The second index between which to determine the maximum.
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+
+ Raises
+ ------
+ SpectrumException
+ When pos1 or pos2 is invalid.
+ """
axis = self.checkAxis(axis)
if not self.noUndo:
copyData = copy.deepcopy(self)
@@ -1170,9 +2021,9 @@ def align(self, pos1=None, pos2=None, axis=-1):
pos1 = 0
if pos2 is None:
pos2 = self.shape()[axis]
- if not (0 <= pos1 <= self.shape()[axis]):
+ if not 0 <= pos1 <= self.shape()[axis]:
raise SpectrumException("Indices not within range")
- if not (0 <= pos2 <= self.shape()[axis]):
+ if not 0 <= pos2 <= self.shape()[axis]:
raise SpectrumException("Indices not within range")
if pos1 == pos2:
raise SpectrumException("Indices cannot be equal")
@@ -1186,15 +2037,17 @@ def align(self, pos1=None, pos2=None, axis=-1):
shape = np.delete(shape, axis)
rangeList = [range(i) for i in shape]
for i in itertools.product(*rangeList):
- selectList = np.insert(np.array(i,dtype=object), axis, slice(None))
+ selectList = np.insert(np.array(i, dtype=object), axis, slice(None))
self.data[selectList] = self.data[selectList].roll(maxArgPos[0][tuple(i)], 0)
self.addHistory("Maxima aligned between " + str(minPos) + " and " + str(maxPos) + " along axis " + str(axis))
self.redoList = []
if not self.noUndo:
self.undoList.append(lambda self: self.restoreData(copyData, lambda self: self.align(pos1, pos2, axis)))
-
- def __fourier(self, axis, tmp=False, reorder=[True,True]):
+
+ def __fourier(self, axis, tmp=False, reorder=None):
axis = self.checkAxis(axis)
+ if reorder is None:
+ reorder = [True, True]
if reorder[0]:
self.data.icomplexReorder(axis)
if not self.wholeEcho[axis] and not tmp:
@@ -1207,8 +2060,10 @@ def __fourier(self, axis, tmp=False, reorder=[True,True]):
self.data.icomplexReorder(axis)
self.resetXax(axis)
- def __invFourier(self, axis, tmp=False, reorder=[True,True]):
+ def __invFourier(self, axis, tmp=False, reorder=None):
axis = self.checkAxis(axis)
+ if reorder is None:
+ reorder = [True, True]
if reorder[0]:
self.data.icomplexReorder(axis)
self.data = self.data.ifftshift(axis).ifft(axis)
@@ -1222,6 +2077,15 @@ def __invFourier(self, axis, tmp=False, reorder=[True,True]):
self.resetXax(axis)
def complexFourier(self, axis=-1):
+ """
+ Perform a complex Fourier transform along a given dimension.
+
+ Parameters
+ ----------
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
if self.spec[axis] == 0:
self.__fourier(axis)
self.addHistory("Fourier transform dimension " + str(axis + 1))
@@ -1233,6 +2097,15 @@ def complexFourier(self, axis=-1):
self.undoList.append(lambda self: self.complexFourier(axis))
def realFourier(self, axis=-1):
+ """
+ Perform a real Fourier transform along a given dimension.
+
+ Parameters
+ ----------
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ """
if not self.noUndo:
copyData = copy.deepcopy(self)
axis = self.checkAxis(axis)
@@ -1248,6 +2121,19 @@ def realFourier(self, axis=-1):
self.undoList.append(lambda self: self.restoreData(copyData, lambda self: self.realFourier(axis)))
def fftshift(self, axis=-1, inv=False):
+ """
+ Perform an fftshift or inverse fftshift along a given dimension.
+ This shifts the zero-frequency component to the center of the spectrum.
+
+ Parameters
+ ----------
+ axis : int, optional
+ The dimension.
+ By default the last dimension is used.
+ inv : bool, optional
+ If True, the inverse fftshift is performed.
+ False by default .
+ """
axis = self.checkAxis(axis)
if inv:
self.data = self.data.ifftshift(axis=axis)
@@ -1260,6 +2146,29 @@ def fftshift(self, axis=-1, inv=False):
self.undoList.append(lambda self: self.fftshift(axis, not(inv)))
def shear(self, shear, axis=-1, axis2=-2, toRef=False):
+ """
+ Shears the data along given axes.
+
+ Parameters
+ ----------
+ shear : float
+ The shearing factor defined in ratio between the x-axes of axis and axis2.
+ axis : int, optional
+ The dimension along which the shearing is applied.
+ By default the last dimension is used.
+ axis2 : int, optional
+ The shearing axis.
+ By default the second last dimension is used.
+ toRef : bool, optional
+ If True, the shearing is applied relative to the reference frequencies of both dimensions.
+ Otherwise the shearing is applied relative to the center of the data.
+ False by default.
+
+ Raises
+ ------
+ SpectrumException
+ When axis2 equals axis or when the data does not have more one dimension.
+ """
axis = self.checkAxis(axis)
axis2 = self.checkAxis(axis2)
if axis == axis2:
@@ -1267,7 +2176,7 @@ def shear(self, shear, axis=-1, axis2=-2, toRef=False):
if self.ndim() < 2:
raise SpectrumException("The data does not have enough dimensions for a shearing transformation")
if self.spec[axis] > 0: #rorder and fft for spec
- self.__invFourier(axis, tmp=True, reorder=[True,False])
+ self.__invFourier(axis, tmp=True, reorder=[True, False])
else: #Reorder if FID
self.data.icomplexReorder(axis)
shape = self.shape()
@@ -1285,7 +2194,7 @@ def shear(self, shear, axis=-1, axis2=-2, toRef=False):
shearMatrix = np.exp(1j * np.outer(vec1, vec2))
self.data *= shearMatrix.reshape(shape)
if self.spec[axis] > 0:
- self.__fourier(axis, tmp=True, reorder=[False,True])
+ self.__fourier(axis, tmp=True, reorder=[False, True])
else:
self.data.icomplexReorder(axis)
self.addHistory("Shearing transform with shearing value " + str(shear) + " over dimensions " + str(axis + 1) + " and " + str(axis2 + 1))
@@ -1293,7 +2202,21 @@ def shear(self, shear, axis=-1, axis2=-2, toRef=False):
if not self.noUndo:
self.undoList.append(lambda self: self.shear(-shear, axis, axis2, toRef))
- def reorder(self, pos, newLength, axis=-1):
+ def reorder(self, pos, newLength=None, axis=-1):
+ """
+ Reorders the data based on a given list of indices.
+
+ Parameters
+ ----------
+ pos : array_like
+ The positions of the subarrays in the new data.
+ newLength : int, optional
+ The new length of the data along axis.
+ By default one more than the largest value in pos is used.
+ axis : int, optional
+ The axis along which the data is reordered.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
if not self.noUndo:
copyData = copy.deepcopy(self)
@@ -1305,11 +2228,25 @@ def reorder(self, pos, newLength, axis=-1):
self.undoList.append(lambda self: self.restoreData(copyData, lambda self: self.reorder(pos, newLength, axis)))
def ffm(self, pos, typeVal, axis=-1):
+ """
+ Uses the fast forward maximum entropy algorithm to reconstruct non-uniform sampled data.
+
+ Parameters
+ ----------
+ pos : array_like
+ A list of indices that are recorded datapoints.
+ All other datapoints will be reconstructed.
+ typeVal : {0, 1, 2}
+ The type of data to be reconstructed.
+ 0=complex, 1=States or States-TPPI, 2=TPPI.
+ axis : int, optional
+ The axis along which the data is reconstructed.
+ By default the last dimension is used.
+ """
axis = self.checkAxis(axis)
if not self.noUndo:
copyData = copy.deepcopy(self)
- # pos contains the values of fixed points which not to be translated to missing points
- posList = np.delete(range(self.shape()[axis]), pos)
+ posList = np.delete(range(self.shape()[axis]), pos) # pos contains the values of fixed points which not to be translated to missing points
if typeVal == 1: # type is States or States-TPPI, the positions need to be divided by 2
posList = np.array(np.floor(posList / 2), dtype=int)
if typeVal == 2: # type is TPPI, for now handle the same as Complex
@@ -1321,24 +2258,42 @@ def ffm(self, pos, typeVal, axis=-1):
tmpShape = tmpData.shape
tmpData = tmpData.reshape((int(tmpData.size / tmpShape[-1]), tmpShape[-1]))
pool = multiprocessing.Pool(multiprocessing.cpu_count())
- fit = pool.map_async(ffm, [(i, posList) for i in tmpData])
+ fit = pool.map_async(nus.ffm, [(i, posList) for i in tmpData])
pool.close()
pool.join()
tmpData = np.rollaxis(np.array(fit.get()).reshape(tmpShape), -1, axis)
self.data = hc.HComplexData(tmpData)
- #Transform back to FID
- self.__invFourier(axis, tmp=True)
+ self.__invFourier(axis, tmp=True) # Transform back to FID
self.addHistory("Fast Forward Maximum Entropy reconstruction of dimension " + str(axis + 1) + " at positions " + str(pos))
self.redoList = []
if not self.noUndo:
self.undoList.append(lambda self: self.restoreData(copyData, None))
def clean(self, pos, typeVal, axis, gamma, threshold, maxIter):
+ """
+ Uses the CLEAN algorithm to reconstruct non-uniform sampled data.
+
+ Parameters
+ ----------
+ pos : array_like
+ A list of indices that are recorded datapoints.
+ All other datapoints will be reconstructed.
+ typeVal : {0, 1, 2}
+ The type of data to be reconstructed.
+ 0=complex, 1=States or States-TPPI, 2=TPPI.
+ axis : int
+ The axis along which the data is reconstructed.
+ gamma : float
+ Gamma value of the CLEAN calculation.
+ threshold : float
+ Stopping limit (0 < x < 1) (stop if residual intensity below this point).
+ maxIter : int
+ Maximum number of iterations.
+ """
axis = self.checkAxis(axis)
if not self.noUndo:
copyData = copy.deepcopy(self)
- # pos contains the values of fixed points which not to be translated to missing points
- posList = np.delete(range(self.shape()[axis]), pos)
+ posList = np.delete(range(self.shape()[axis]), pos) # pos contains the values of fixed points which not to be translated to missing points
if typeVal == 1: # type is States or States-TPPI, the positions need to be divided by 2
posList = np.array(np.floor(posList / 2), dtype=int)
if typeVal == 2: # type is TPPI, for now handle the same as Complex
@@ -1353,28 +2308,44 @@ def clean(self, pos, typeVal, axis, gamma, threshold, maxIter):
mask[posList] = 0.0
mask = np.fft.fft(mask) # abs or real???
pool = multiprocessing.Pool(multiprocessing.cpu_count())
- fit = pool.map_async(clean, [(i, mask, gamma, threshold, maxIter) for i in tmpData])
+ fit = pool.map_async(nus.clean, [(i, mask, gamma, threshold, maxIter) for i in tmpData])
pool.close()
pool.join()
tmpData = np.rollaxis(np.array(fit.get()).reshape(tmpShape), -1, axis)
self.data = hc.HComplexData(tmpData)
- #Transform back to FID
- self.__invFourier(axis, tmp=True)
- self.addHistory("CLEAN reconstruction (gamma = " + str(gamma) + " , threshold = " + str(threshold) + " , maxIter = " + str(maxIter) + ") " +
- "of dimension " + str(axis + 1) + " at positions " + str(pos))
+ self.__invFourier(axis, tmp=True) # Transform back to FID
+ self.addHistory("CLEAN reconstruction (gamma = " + str(gamma) + " , threshold = " + str(threshold) + " , maxIter = " + str(maxIter) + ") " + "of dimension " + str(axis + 1) + " at positions " + str(pos))
self.redoList = []
if not self.noUndo:
self.undoList.append(lambda self: self.restoreData(copyData, None))
-
- def ist(self,pos, typeVal, axis, threshold, maxIter, tracelimit):
- import scipy.signal
+
+ def ist(self, pos, typeVal, axis, threshold, maxIter, tracelimit):
+ """
+ Uses the Iterative Soft Thresholding algorithm to reconstruct non-uniform sampled data.
+
+ Parameters
+ ----------
+ pos : array_like
+ A list of indices that are recorded datapoints.
+ All other datapoints will be reconstructed.
+ typeVal : {0, 1, 2}
+ The type of data to be reconstructed.
+ 0=complex, 1=States or States-TPPI, 2=TPPI.
+ axis : int
+ The axis along which the data is reconstructed.
+ threshold : float
+ threshold. The level (0 < x < 1) at which the data is cut every iteration.
+ maxIter : int
+ Maximum number of iterations.
+ tracelimit : float
+ Stopping limit (0 < x < 1) (stop if residual intensity below this point).
+ """
axis = self.checkAxis(axis)
if not self.noUndo:
copyData = copy.deepcopy(self)
- # pos contains the values of fixed points which not to be translated to missing points
self.data.icomplexReorder(axis)
tmpData = self.data.getHyperData(0)
- posList = np.delete(range(tmpData.shape[axis]), pos)
+ posList = np.delete(range(tmpData.shape[axis]), pos) # pos contains the values of fixed points which not to be translated to missing points
if typeVal == 1: # type is States or States-TPPI, the positions need to be divided by 2
posList = np.array(np.floor(posList / 2), dtype=int)
elif typeVal == 2: # type is TPPI, for now handle the same as Complex
@@ -1384,20 +2355,37 @@ def ist(self,pos, typeVal, axis, threshold, maxIter, tracelimit):
tmpShape = tmpData.shape
tmpData = tmpData.reshape((int(tmpData.size / tmpShape[-1]), tmpShape[-1]))
pool = multiprocessing.Pool(multiprocessing.cpu_count())
- fit = pool.map_async(ist, [(i, posList, threshold, maxIter, tracelimit, NDmax) for i in tmpData])
+ fit = pool.map_async(nus.ist, [(i, posList, threshold, maxIter, tracelimit, NDmax) for i in tmpData])
pool.close()
pool.join()
tmpData = np.rollaxis(np.array(fit.get()).reshape(tmpShape), -1, axis)
self.data = hc.HComplexData(tmpData)
- #Transform back to FID
- self.__invFourier(axis, tmp=True)
- self.addHistory("IST reconstruction (threshold = " + str(threshold) + " , maxIter = " + str(maxIter) + " , tracelimit = " + str(tracelimit*100) + ") " +
- "of dimension " + str(axis + 1) + " at positions " + str(pos))
+ self.__invFourier(axis, tmp=True) # Transform back to FID
+ self.addHistory("IST reconstruction (threshold = " + str(threshold) + " , maxIter = " + str(maxIter) + " , tracelimit = " + str(tracelimit*100) + ") " + "of dimension " + str(axis + 1) + " at positions " + str(pos))
self.redoList = []
if not self.noUndo:
self.undoList.append(lambda self: self.restoreData(copyData, None))
def getSlice(self, axes, locList, stack=None):
+ """
+ Generate a new Spectrum object which is a subset of this object.
+
+ Parameters
+ ----------
+ axes : array_like
+ A list with the axes desired in the new object.
+ locList : array_like
+ The indices to specify the desired data subset.
+ stack : array_like, optional
+ Slice objects to extract part of an axis.
+ Often used for stack or array plots.
+ By default the entire data along all axes are used.
+
+ Returns
+ -------
+ Spectrum
+ The subset spectrum.
+ """
locList = np.array(locList, dtype=object)
if stack is None:
stack = [slice(None)]*len(axes)
@@ -1420,8 +2408,19 @@ def getSlice(self, axes, locList, stack=None):
name=self.name))
sliceSpec.noUndo = True
return sliceSpec
-
- def restoreData(self, copyData, returnValue): # restore data from an old copy for undo purposes
+
+ def restoreData(self, copyData, returnValue):
+ """
+ Restore data from an old copy.
+ Often used for undo purposes.
+
+ Parameters
+ ----------
+ copyData : Spectrum
+ The old Spectrum object to restore from.
+ returnValue
+ A return value that should be appended to the undolist.
+ """
if (not self.noUndo) and returnValue is None:
copyData2 = copy.deepcopy(self)
self.data = copyData.data
diff --git a/src/spectrumFrame.py b/src/spectrumFrame.py
index b9f7915a..62fa0997 100644
--- a/src/spectrumFrame.py
+++ b/src/spectrumFrame.py
@@ -21,7 +21,7 @@
import numpy as np
import matplotlib as mpl
import matplotlib.gridspec as gridspec
-from ssNake import QtGui, QtCore, QtWidgets
+from ssNake import QtCore, QtWidgets
TIMELABELLIST = [u'[s]', u'[ms]', u'[μs]']
FREQLABELLIST = [u'[Hz]', u'[kHz]', u'[MHz]']
@@ -30,14 +30,30 @@
# the class from which the 1d data is displayed, the operations which only edit the content of this class are for previewing
-class PlotFrame(object):
+class PlotFrame:
+ """
+ The frame used to display the plot.
+ It handles the mouse actions applied to the figure.
+ """
+
+ INVERT_X = True # Invert the x-axis when spectrum
+ INVERT_Y = False # Invert the y-axis when spectrum
+ GRID_PLOT = False # Grid plot for contour
+ ZERO_SCROLL_ALLOWED = True # Scroll with respect to 0 on the y-axis
- INVERT_X = True # Invert the x-axis when spectrum
- INVERT_Y = False # Invert the y-axis when spectrum
- GRID_PLOT = False # Grid plot for contour
- ZERO_SCROLL_ALLOWED = True # Scroll with respect to 0 on the y-axis
-
def __init__(self, root, fig, canvas):
+ """
+ Initializes the PlotFrame.
+
+ Parameters
+ ----------
+ root : Main1DWindow
+ The window that contains the figure.
+ fig : Figure
+ The figure used in this frame.
+ canvas : FigureCanvas
+ The canvas of fig.
+ """
self.root = root
self.fig = fig
self.canvas = canvas
@@ -62,7 +78,7 @@ def __init__(self, root, fig, canvas):
self.x_ax.axes.get_xaxis().set_visible(False)
self.x_ax.axes.get_yaxis().set_visible(False)
self.y_ax.axes.get_xaxis().set_visible(False)
- self.y_ax.axes.get_yaxis().set_visible(False)
+ self.y_ax.axes.get_yaxis().set_visible(False)
else:
self.ax = self.fig.add_subplot(111)
self.leftMouse = False # is the left mouse button currently pressed
@@ -79,9 +95,11 @@ def __init__(self, root, fig, canvas):
# variables to be initialized
def kill(self):
+ """Dummy method"""
pass
- def plotReset(self): # this function needs to be overriden by the classes who inherit from PlotFrame
+ def plotReset(self):
+ """Dummy method"""
pass
################
@@ -89,6 +107,10 @@ def plotReset(self): # this function needs to be overriden by the classes who i
################
def peakPickReset(self):
+ """
+ Resets the figure after peak picking.
+ It removes any lines created by peak peaking still in the figure.
+ """
if self.rect[0] is not None:
try:
self.rect[0].remove()
@@ -106,8 +128,17 @@ def peakPickReset(self):
self.peakPickFunc = None
def scroll(self, event):
+ """
+ Handles scrolling in the figure.
+ The effect depends on the buttons that were held during scrolling.
+
+ Parameters
+ ----------
+ event : QEvent
+ The event.
+ """
zoomStep = self.root.father.defaultZoomStep
- event.step = event.step * zoomStep #Apply zoom sensitivity
+ event.step = event.step * zoomStep # Apply zoom sensitivity
modifiers = QtWidgets.QApplication.keyboardModifiers()
if modifiers == QtCore.Qt.ShiftModifier:
self.altScroll(event)
@@ -161,18 +192,29 @@ def scroll(self, event):
self.yminlim *= 0.9**event.step
self.ax.set_ylim(self.yminlim, self.ymaxlim)
if self.INVERT_Y:
- if self.spec(-2) > 0 :
+ if self.spec(-2) > 0:
self.ax.set_ylim(self.ymaxlim, self.yminlim)
self.canvas.update()
self.canvas.draw_idle()
def altScroll(self, event):
+ """Dummy method"""
pass
def altReset(self):
+ """Dummy method"""
pass
def buttonPress(self, event):
+ """
+ Handles button presses in the figure.
+ The effect depends on the buttons that were held during the button press and whether peak picking is enabled.
+
+ Parameters
+ ----------
+ event : QEvent
+ The event.
+ """
if event.button == 1 and not self.peakPick:
self.leftMouse = True
self.zoomX1 = event.xdata
@@ -189,6 +231,15 @@ def buttonPress(self, event):
self.panY = event.ydata
def buttonRelease(self, event):
+ """
+ Handles button release in the figure.
+ The effect depends on the buttons that were held during the button release and whether peak picking is enabled.
+
+ Parameters
+ ----------
+ event : QEvent
+ The event.
+ """
if event.button == 1:
if self.peakPick:
if self.rect[0] is not None:
@@ -242,7 +293,15 @@ def buttonRelease(self, event):
self.canvas.draw_idle()
def pan(self, event):
- modifiers = QtWidgets.QApplication.keyboardModifiers()
+ """
+ Handles panning in the figure.
+ The effect depends on the buttons that were held during panning and whether peak picking is enabled.
+
+ Parameters
+ ----------
+ event : QEvent
+ The event.
+ """
if self.rightMouse and self.panX is not None and self.panY is not None:
if self.logx or self.logy:
x = event.xdata
@@ -338,7 +397,32 @@ def pan(self, event):
self.canvas.draw_idle()
def getAxMult(self, spec, axType, ppm, freq, ref=None):
- if spec == 1:
+ """
+ Calculates the x-axis multiplier to convert the xax to a given axis type.
+
+ Parameters
+ ----------
+ spec : bool
+ True if the axis is for a spectrum, False it is for an FID.
+ axType : int
+ The multiplier defined as 1000^axType for spectra and 1000^-axType for FIDs.
+ When ppm is True this is not applied.
+ ppm : bool
+ If True the multiplier is calculated to convert to a ppm axis.
+ This is only used when spec is True.
+ freq : float
+ The spectrometer frequency (only used when spec is True).
+ ref : float, optional
+ The reference frequency if None the spectrometer frequency is used.
+ None by default.
+ Only used when spec is True.
+
+ Returns
+ -------
+ float
+ The x-axis multiplier.
+ """
+ if spec:
if ppm:
if ref is not None:
axMult = 1e6 / ref
@@ -346,24 +430,51 @@ def getAxMult(self, spec, axType, ppm, freq, ref=None):
axMult = 1e6 / freq
else:
axMult = 1.0 / (1000.0**axType)
- elif spec == 0:
+ else:
axMult = 1000.0**axType
return axMult
def getLabel(self, spec, axis, axType, ppm):
+ """
+ Generates the axis label for a given axis type and dimension.
+
+ Parameters
+ ----------
+ spec : bool
+ True if the axis is for a spectrum, False it is for an FID.
+ axis : int
+ The dimension of the axis.
+ axType : int
+ 0 for Hz/s, 1 for kHz/ms, 2 for MHz/us.
+ ppm : bool
+ True if the frequency axis is in ppm.
+
+ Returns
+ -------
+ str
+ The axis label.
+ """
if not axType in range(3):
return 'User defined D' + str(axis+1)
if spec:
tmpString = "Frequency D" + str(axis+1) + ' '
if ppm:
return tmpString + '[ppm]'
- else:
- return tmpString + FREQLABELLIST[axType]
+ return tmpString + FREQLABELLIST[axType]
else:
-
return "Time D" + str(axis+1) + ' ' + TIMELABELLIST[axType]
def setLog(self, logx, logy):
+ """
+ Sets the x and y axis to logarithmic or linear.
+
+ Parameters
+ ----------
+ logx : bool
+ True for a logarithmic x-axis.
+ logy : bool
+ True for a logarithmic y-axis.
+ """
self.logx = logx
self.logy = logy
self.ax.set_xlim(self.xminlim, self.xmaxlim)
diff --git a/src/ssNake.py b/src/ssNake.py
index 81c3f474..6971e70f 100644
--- a/src/ssNake.py
+++ b/src/ssNake.py
@@ -62,7 +62,7 @@ def splashProgressStep(splashStep): # A function to easily increase the progres
root.processEvents()
return splashStep
-def import_lib(name,nameAs,className,splashStep):
+def import_lib(name, nameAs, className, splashStep):
# Function to load a library from string names
if className is None:
globals()[nameAs] = importlib.import_module(name)
@@ -77,7 +77,7 @@ def import_lib(name,nameAs,className,splashStep):
['traceback', 'tb', None],
['numpy', 'np', None],
['copy', 'copy', None],
- ['multiprocessing','multiprocessing',None],
+ ['multiprocessing', 'multiprocessing', None],
['datetime', 'datetime', None],
['webbrowser', 'webbrowser', None],
['spectrum', 'sc', None],
@@ -91,31 +91,29 @@ def import_lib(name,nameAs,className,splashStep):
['specIO', 'io', None],
['views', 'views', None],
['simFunctions', 'sim', None],
- ['loadIsotopes','loadIsotopes',None],
- ['scipy','optimize','optimize']]
+ ['loadIsotopes', 'loadIsotopes', None],
+ ['scipy', 'optimize', 'optimize']]
splashSteps = len(importList) / 100.0
splashStep = 0
# Import everything else
for elem in importList:
- splashStep = import_lib(elem[0],elem[1],elem[2],splashStep)
-
+ splashStep = import_lib(elem[0], elem[1], elem[2], splashStep)
isoPath = os.path.dirname(os.path.realpath(__file__)) + os.path.sep + "IsotopeProperties"
ISOTOPES = loadIsotopes.getIsotopeInfo(isoPath)
-
matplotlib.rc('font', family='DejaVu Sans')
np.set_printoptions(threshold=sys.maxsize)
QtCore.QLocale.setDefault(QtCore.QLocale('en_US'))
-VERSION = 'v1.1'
+VERSION = 'v1.2'
# Required library version
NPVERSION = '1.11.0'
-MPLVERSION = '1.4.2'
+MPLVERSION = '1.5.0'
SPVERSION = '0.14.1'
PY2VERSION = '2.7'
PY3VERSION = '3.4'
-def splitString(val,size):
+def splitString(val, size):
#Split a string at spaces, with maxsize 'size'
total = ''
while len(val) > size:
@@ -126,16 +124,15 @@ def splitString(val,size):
total = total + val
return total
-
#Prepare TOOLTIPS dictionary
TOOLTIPS = dict()
-with open(os.path.dirname(os.path.realpath(__file__)) + os.path.sep + 'Tooltips','r') as f:
+with open(os.path.dirname(os.path.realpath(__file__)) + os.path.sep + 'Tooltips', 'r') as f:
data = f.read().split('\n')
for line in data:
- if len(line) > 0:
+ if line:
tmp = line.split('\t')
if len(tmp) > 2:
- text = tmp[1] + '\n\n' + splitString(tmp[2],80) #Header plus split main text
+ text = tmp[1] + '\n\n' + splitString(tmp[2], 80) #Header plus split main text
else:
text = tmp[1]
TOOLTIPS[tmp[0]] = text
@@ -171,9 +168,12 @@ def __init__(self, root):
self.lastLocation = os.path.expanduser('~')
else:
self.lastLocation = os.getcwd()
+ if not self.defaultTooltips: #Disable tooltips by setting them to empty strings
+ for elem in TOOLTIPS.keys():
+ TOOLTIPS[elem] = ''
self.initMenu()
self.menuCheck()
- self.main_widget = QtWidgets.QSplitter(self)
+ self.main_widget = QtWidgets.QSplitter(self)
self.main_widget.setHandleWidth(10)
self.gridWidget = QtWidgets.QWidget(self)
self.mainFrame = QtWidgets.QGridLayout(self.gridWidget)
@@ -222,7 +222,7 @@ def handleCopy(self):
""" Makes a pixelwise copy of the currently viewed canvas """
if self.mainWindow is None:
return
- if issubclass(type(self.mainWindow),fit.TabFittingWindow): #If fitting, take canvas from current tab
+ if issubclass(type(self.mainWindow), fit.TabFittingWindow): #If fitting, take canvas from current tab
canvas = self.mainWindow.tabs.currentWidget().canvas
else:
canvas = self.mainWindow.canvas
@@ -260,6 +260,7 @@ def resetDefaults(self):
self.defaultNegColor = '#FF7F0E'
self.defaultStartupBool = False
self.defaultStartupDir = '~'
+ self.defaultTooltips = True
self.defaultToolbarActionList = ['File --> Open',
'File -- > Save --> Matlab',
'File --> Export --> Figure',
@@ -347,6 +348,7 @@ def loadDefaults(self):
self.defaultToolBar = settings.value("toolbar", self.defaultToolBar, bool)
self.defaultStartupBool = settings.value("startupdiron", self.defaultStartupBool, bool)
self.defaultStartupDir = settings.value("startupdir", self.defaultStartupDir, str)
+ self.defaultTooltips = settings.value("tooltips", self.defaultTooltips, bool)
try:
self.defaultWidthRatio = settings.value("contour/width_ratio", self.defaultWidthRatio, float)
except TypeError:
@@ -381,6 +383,7 @@ def saveDefaults(self):
settings.setValue("toolbar", self.defaultToolBar)
settings.setValue("startupdiron", self.defaultStartupBool)
settings.setValue("startupdir", self.defaultStartupDir)
+ settings.setValue("tooltips", self.defaultTooltips)
settings.setValue("contour/colourmap", self.defaultColorMap)
settings.setValue("contour/constantcolours", self.defaultContourConst)
settings.setValue("contour/poscolour", self.defaultPosColor)
@@ -505,6 +508,7 @@ def initToolbar(self):
['Plot --> Stack Plot', self.stackplotAct],
['Plot --> Array Plot', self.arrayplotAct],
['Plot --> Contour Plot', self.contourplotAct],
+ ['Plot --> 2D Colour Plot', self.colour2DplotAct],
['Plot --> Multi Plot', self.multiplotAct],
['Plot --> Set Reference', self.setrefAct],
['Plot --> Clear Current Reference', self.delrefAct],
@@ -567,7 +571,7 @@ def initMenu(self):
self.menubar.addMenu(self.workspacemenu)
self.newAct = self.workspacemenu.addAction(QtGui.QIcon(IconDirectory + 'duplicate.png'), 'D&uplicate', self.duplicateWorkspace, QtGui.QKeySequence.New)
self.newAct.setToolTip('Duplicate Workspace')
- self.newSlice = self.workspacemenu.addAction(QtGui.QIcon(IconDirectory + 'duplicate.png'), 'Slice to Workspace', lambda: self.duplicateWorkspace(sliceOnly = True))
+ self.newSlice = self.workspacemenu.addAction(QtGui.QIcon(IconDirectory + 'duplicate.png'), 'Slice to Workspace', lambda: self.duplicateWorkspace(sliceOnly=True))
self.newSlice.setToolTip('Copy Current Slice to New Workspace')
self.closeAct = self.workspacemenu.addAction(QtGui.QIcon(IconDirectory + 'delete.png'), '&Delete', self.destroyWorkspace, QtGui.QKeySequence.Close)
self.closeAct.setToolTip('Delete Workspace')
@@ -582,7 +586,7 @@ def initMenu(self):
self.workInfoAct = self.workspacemenu.addAction(QtGui.QIcon(IconDirectory + 'about.png'), '&Info', lambda: self.mainWindowCheck(lambda mainWindow: WorkInfoWindow(mainWindow)))
self.workInfoAct.setToolTip('Workspace Information')
self.workspaceActList = [self.newAct, self.newSlice, self.closeAct, self.renameWorkspaceAct,
- self.forwardAct, self.backAct,self.workInfoAct]
+ self.forwardAct, self.backAct, self.workInfoAct]
# Macro menu
self.macromenu = QtWidgets.QMenu('&Macros', self)
self.menubar.addMenu(self.macromenu)
@@ -660,7 +664,7 @@ def initMenu(self):
self.digitalFilterAct.setToolTip("Correct Digital Filter")
self.lpsvdAct = self.toolMenu.addAction(QtGui.QIcon(IconDirectory + 'LPSVD.png'), "&LPSVD", lambda: self.mainWindowCheck(lambda mainWindow: LPSVDWindow(mainWindow)))
self.lpsvdAct.setToolTip('LPSVD linear prediction')
- self.scaleSWAct = self.toolMenu.addAction(QtGui.QIcon(IconDirectory + 'ScaleSW.png'),"Scale SW", lambda: self.mainWindowCheck(lambda mainWindow: ScaleSWWindow(mainWindow)))
+ self.scaleSWAct = self.toolMenu.addAction(QtGui.QIcon(IconDirectory + 'ScaleSW.png'), "Scale SW", lambda: self.mainWindowCheck(lambda mainWindow: ScaleSWWindow(mainWindow)))
self.scaleSWAct.setToolTip('Scale the Current Spectral Width')
self.referencelistmenu = QtWidgets.QMenu('&Reference', self)
self.toolMenu.addMenu(self.referencelistmenu)
@@ -678,10 +682,10 @@ def initMenu(self):
self.referencelistmenu.addMenu(self.referencesavemenu)
self.loadrefAct = self.referencelistmenu.addAction(QtGui.QIcon(IconDirectory + 'open.png'), "&Load", self.referenceLoad)
self.loadrefAct.setToolTip('Load Reference')
- self.toolsActList = [self.realAct, self.imagAct, self.absAct,self.conjAct,
+ self.toolsActList = [self.realAct, self.imagAct, self.absAct, self.conjAct,
self.apodizeAct, self.phaseAct, self.autoPhaseAct0,
- self.autoPhaseAct1, self.autoPhaseAllAct0, self.phasingmenu,
- self.autoPhaseAllAct1,self.swapEchoAct, self.corOffsetAct,
+ self.autoPhaseAct1, self.autoPhaseAllAct0, self.phasingmenu,
+ self.autoPhaseAllAct1, self.swapEchoAct, self.corOffsetAct,
self.baselineAct, self.subAvgAct, self.refDeconvAct, self.lpsvdAct,
self.digitalFilterAct, self.scaleSWAct]
# the matrix drop down menu
@@ -691,9 +695,9 @@ def initMenu(self):
self.sizingAct.setToolTip('Set Size')
self.shiftAct = self.matrixMenu.addAction(QtGui.QIcon(IconDirectory + 'shift.png'), "S&hift Data", lambda: self.mainWindowCheck(lambda mainWindow: ShiftDataWindow(mainWindow)))
self.shiftAct.setToolTip('Shift Data')
- self.rollAct = self.matrixMenu.addAction(QtGui.QIcon(IconDirectory + 'roll.png'),"Roll Data", lambda: self.mainWindowCheck(lambda mainWindow: RollDataWindow(mainWindow)))
+ self.rollAct = self.matrixMenu.addAction(QtGui.QIcon(IconDirectory + 'roll.png'), "Roll Data", lambda: self.mainWindowCheck(lambda mainWindow: RollDataWindow(mainWindow)))
self.rollAct.setToolTip('Roll Data')
- self.alignAct = self.matrixMenu.addAction(QtGui.QIcon(IconDirectory + 'alignMax.png'),"Align Maxima", lambda: self.mainWindowCheck(lambda mainWindow: AlignDataWindow(mainWindow)))
+ self.alignAct = self.matrixMenu.addAction(QtGui.QIcon(IconDirectory + 'alignMax.png'), "Align Maxima", lambda: self.mainWindowCheck(lambda mainWindow: AlignDataWindow(mainWindow)))
self.alignAct.setToolTip('Align Maxima')
self.regionMenu = QtWidgets.QMenu("Region", self)
self.matrixMenu.addMenu(self.regionMenu)
@@ -774,8 +778,8 @@ def initMenu(self):
self.echoantiAct = self.hypercomplexMenu.addAction(QtGui.QIcon(IconDirectory + 'echoantiecho.png'), "Ec&ho-antiecho", lambda: self.mainWindowCheck(lambda mainWindow: mainWindow.echoAntiEcho()))
self.echoantiAct.setToolTip('Ec&ho-antiecho Hypercomplex Data Processing')
self.transformActList = [self.fourierAct, self.realFourierAct, self.fftshiftAct,
- self.invfftshiftAct, self.hilbertAct, self.ffmAct,
- self.cleanAct, self.istAct,self.statesAct,self.statesTPPIAct,self.echoantiAct]
+ self.invfftshiftAct, self.hilbertAct, self.ffmAct,
+ self.cleanAct, self.istAct, self.statesAct, self.statesTPPIAct, self.echoantiAct]
# the fitting drop down menu
self.fittingMenu = QtWidgets.QMenu("F&itting", self)
self.menubar.addMenu(self.fittingMenu)
@@ -785,7 +789,7 @@ def initMenu(self):
self.fwhmAct.setToolTip('Full Width at Half Maximum')
self.massAct = self.fittingMenu.addAction(QtGui.QIcon(IconDirectory + 'mass.png'), "Centre of Mass", lambda: self.mainWindowCheck(lambda mainWindow: COMWindow(mainWindow)))
self.massAct.setToolTip('Centre of Mass')
- self.intfitAct = self.fittingMenu.addAction(QtGui.QIcon(IconDirectory + 'int.png'),"&Integrals", lambda: self.mainWindowCheck(lambda mainWindow: IntegralsWindow(mainWindow)))
+ self.intfitAct = self.fittingMenu.addAction(QtGui.QIcon(IconDirectory + 'int.png'), "&Integrals", lambda: self.mainWindowCheck(lambda mainWindow: IntegralsWindow(mainWindow)))
self.intfitAct.setToolTip('Get Integrals')
self.relaxAct = self.fittingMenu.addAction(QtGui.QIcon(IconDirectory + 'relaxation.png'), "&Relaxation Curve", lambda: self.mainWindowCheck(lambda mainWindow: mainWindow.createRelaxWindow()))
self.relaxAct.setToolTip('Fit Relaxation Curve')
@@ -797,17 +801,17 @@ def initMenu(self):
self.csastaticAct.setToolTip('Fit CSA')
self.quadAct = self.fittingMenu.addAction(QtGui.QIcon(IconDirectory + 'quadconversion.png'), "&Quadrupole", lambda: self.mainWindowCheck(lambda mainWindow: mainWindow.createQuadDeconvWindow()))
self.quadAct.setToolTip('Fit Quadrupole')
- self.quadCSAAct = self.fittingMenu.addAction(QtGui.QIcon(IconDirectory + 'quadcsa.png'),"Q&uadrupole+CSA", lambda: self.mainWindowCheck(lambda mainWindow: mainWindow.createQuadCSADeconvWindow()))
+ self.quadCSAAct = self.fittingMenu.addAction(QtGui.QIcon(IconDirectory + 'quadcsa.png'), "Q&uadrupole+CSA", lambda: self.mainWindowCheck(lambda mainWindow: mainWindow.createQuadCSADeconvWindow()))
self.quadCSAAct.setToolTip('Fit Quadrupole+CSA')
self.czjzekAct = self.fittingMenu.addAction(QtGui.QIcon(IconDirectory + 'czjzekstatic.png'), "C&zjzek", lambda: self.mainWindowCheck(lambda mainWindow: mainWindow.createQuadCzjzekWindow()))
self.czjzekAct.setToolTip('Fit Czjzek Pattern')
- self.mqmasAct = self.fittingMenu.addAction(QtGui.QIcon(IconDirectory + 'mqmas.png'),"&MQMAS", lambda: self.mainWindowCheck(lambda mainWindow: mainWindow.createMQMASWindow()))
+ self.mqmasAct = self.fittingMenu.addAction(QtGui.QIcon(IconDirectory + 'mqmas.png'), "&MQMAS", lambda: self.mainWindowCheck(lambda mainWindow: mainWindow.createMQMASWindow()))
self.mqmasAct.setToolTip('Fit MQMAS')
- self.mqmasCzjzekAct = self.fittingMenu.addAction(QtGui.QIcon(IconDirectory + 'mqmas.png'),"Cz&jzek MQMAS", lambda: self.mainWindowCheck(lambda mainWindow: mainWindow.createMQMASCzjzekWindow()))
+ self.mqmasCzjzekAct = self.fittingMenu.addAction(QtGui.QIcon(IconDirectory + 'mqmas.png'), "Cz&jzek MQMAS", lambda: self.mainWindowCheck(lambda mainWindow: mainWindow.createMQMASCzjzekWindow()))
self.mqmasCzjzekAct.setToolTip('Fit Czjzek MQMAS')
- self.externalFitAct = self.fittingMenu.addAction(QtGui.QIcon(IconDirectory + 'simpson.png'),"&External", lambda: self.mainWindowCheck(lambda mainWindow: mainWindow.createExternalFitWindow()))
+ self.externalFitAct = self.fittingMenu.addAction(QtGui.QIcon(IconDirectory + 'simpson.png'), "&External", lambda: self.mainWindowCheck(lambda mainWindow: mainWindow.createExternalFitWindow()))
self.externalFitAct.setToolTip('Fit External')
- self.functionFitAct = self.fittingMenu.addAction(QtGui.QIcon(IconDirectory + 'function.png'),"F&unction fit", lambda: self.mainWindowCheck(lambda mainWindow: mainWindow.createFunctionFitWindow()))
+ self.functionFitAct = self.fittingMenu.addAction(QtGui.QIcon(IconDirectory + 'function.png'), "F&unction fit", lambda: self.mainWindowCheck(lambda mainWindow: mainWindow.createFunctionFitWindow()))
self.functionFitAct.setToolTip('Fit Function')
self.fittingActList = [self.snrAct, self.fwhmAct, self.massAct,
self.intfitAct, self.relaxAct, self.diffusionAct,
@@ -846,6 +850,10 @@ def initMenu(self):
self.contourplotAct = self.plotMenu.addAction(QtGui.QIcon(IconDirectory + 'contour.png'), "&Contour Plot", lambda: self.mainWindowCheck(lambda mainWindow: mainWindow.plotContour()))
self.contourplotAct.setToolTip('Contour Plot')
self.multiDActions.append(self.contourplotAct)
+
+ self.colour2DplotAct = self.plotMenu.addAction(QtGui.QIcon(IconDirectory + '2DColour.png'), "2D Colour Plot", lambda: self.mainWindowCheck(lambda mainWindow: mainWindow.plotColour2D()))
+ self.colour2DplotAct.setToolTip('2D Colour Plot')
+ self.multiDActions.append(self.colour2DplotAct)
self.multiplotAct = self.plotMenu.addAction(QtGui.QIcon(IconDirectory + 'multi.png'), "&Multi Plot", lambda: self.mainWindowCheck(lambda mainWindow: mainWindow.plotMulti()))
self.multiplotAct.setToolTip('Multi Plot')
#==========
@@ -854,7 +862,7 @@ def initMenu(self):
self.plotprefAct = self.plotMenu.addAction(QtGui.QIcon(IconDirectory + 'preferences.png'), "&Plot Settings", lambda: self.mainWindowCheck(lambda mainWindow: PlotSettingsWindow(mainWindow)))
self.plotprefAct.setToolTip('Plot Settings')
self.plotActList = [self.onedplotAct, self.scatterplotAct, self.stackplotAct,
- self.arrayplotAct, self.contourplotAct, self.multiplotAct,
+ self.arrayplotAct, self.contourplotAct,self.colour2DplotAct, self.multiplotAct,
self.setrefAct, self.delrefAct, self.userxAct, self.plotprefAct]
# the history drop down menu
self.historyMenu = QtWidgets.QMenu("&History", self)
@@ -869,64 +877,46 @@ def initMenu(self):
self.menubar.addMenu(self.utilitiesMenu)
self.shiftconvAct = self.utilitiesMenu.addAction(QtGui.QIcon(IconDirectory + 'shifttool.png'), "&Chemical Shift Conversion Tool", self.createShiftConversionWindow)
self.shiftconvAct.setToolTip('Chemical Shift Conversion Tool')
- self.dipolarconvAct = self.utilitiesMenu.addAction(QtGui.QIcon(IconDirectory + 'dipolar.png'),"Dipolar Distance Tool", self.createDipolarDistanceWindow)
+ self.dipolarconvAct = self.utilitiesMenu.addAction(QtGui.QIcon(IconDirectory + 'dipolar.png'), "Dipolar Distance Tool", self.createDipolarDistanceWindow)
self.dipolarconvAct.setToolTip('Dipolar Distance Tool')
self.quadconvAct = self.utilitiesMenu.addAction(QtGui.QIcon(IconDirectory + 'quadconversion.png'), "&Quadrupole Coupling Conversion Tool", self.createQuadConversionWindow)
self.quadconvAct.setToolTip('Quadrupole Coupling Conversion Tool')
- self.mqmasconvAct = self.utilitiesMenu.addAction(QtGui.QIcon(IconDirectory + 'mqmas.png'),"MQMAS Parameter Extraction Tool", self.createMqmasExtractWindow)
+ self.mqmasconvAct = self.utilitiesMenu.addAction(QtGui.QIcon(IconDirectory + 'mqmas.png'), "MQMAS Parameter Extraction Tool", self.createMqmasExtractWindow)
self.mqmasconvAct.setToolTip('MQMAS Parameter Extraction Tool')
- self.tempcalAct = self.utilitiesMenu.addAction(QtGui.QIcon(IconDirectory + 'temperature.png'),"Temperature Calibration Tool", self.createTempcalWindow)
+ self.tempcalAct = self.utilitiesMenu.addAction(QtGui.QIcon(IconDirectory + 'temperature.png'), "Temperature Calibration Tool", self.createTempcalWindow)
self.tempcalAct.setToolTip('Dipolar Distance Tool')
self.nmrtableAct = self.utilitiesMenu.addAction(QtGui.QIcon(IconDirectory + 'table.png'), "&NMR Table", self.nmrTable)
self.nmrtableAct.setToolTip('NMR Periodic Table')
- self.utilitiesActList = [self.shiftconvAct, self.quadconvAct, self.nmrtableAct, self.dipolarconvAct,self.mqmasconvAct,self.tempcalAct ]
+ self.utilitiesActList = [self.shiftconvAct, self.quadconvAct, self.nmrtableAct, self.dipolarconvAct, self.mqmasconvAct, self.tempcalAct]
# the help drop down menu
self.helpMenu = QtWidgets.QMenu("&Help", self)
self.menubar.addMenu(self.helpMenu)
if not EXE:
self.updateAct = self.helpMenu.addAction(QtGui.QIcon(IconDirectory + 'update.png'), "&Update", self.updateMenu)
self.updateAct.setToolTip('Update ssNake')
- self.helpActList = [self.updateAct]
+ self.helpActList = [self.updateAct]
else:
- self.helpActList = []
- self.refmanAct = self.helpMenu.addAction(QtGui.QIcon(IconDirectory + 'manual.png'),"Reference Manual", lambda: self.openRefMan())
+ self.helpActList = []
+ self.refmanAct = self.helpMenu.addAction(QtGui.QIcon(IconDirectory + 'manual.png'), "Reference Manual", openRefMan)
self.refmanAct.setToolTip('Open the Reference Manual')
- self.basTutorialAct = self.helpMenu.addAction(QtGui.QIcon(IconDirectory + 'Tutorial.png'),"Basic Tutorial", lambda: self.openTutorial())
+ self.basTutorialAct = self.helpMenu.addAction(QtGui.QIcon(IconDirectory + 'Tutorial.png'), "Basic Tutorial", openTutorial)
self.basTutorialAct.setToolTip('Open the Tutorial Folder')
- self.tutorialAct = self.helpMenu.addAction(QtGui.QIcon(IconDirectory + 'Tutorial.png'),"Advanced Tutorials", lambda: webbrowser.open('https://github.com/smeerten/ssnake_tutorials/'))
+ self.tutorialAct = self.helpMenu.addAction(QtGui.QIcon(IconDirectory + 'Tutorial.png'), "Advanced Tutorials", lambda: webbrowser.open('https://github.com/smeerten/ssnake_tutorials/'))
self.tutorialAct.setToolTip('Link to ssNake Advanced Processing Tutorials')
- self.githubAct = self.helpMenu.addAction(QtGui.QIcon(IconDirectory + 'GitHub.png'),"GitHub Page", lambda: webbrowser.open('https://github.com/smeerten/ssnake/'))
+ self.githubAct = self.helpMenu.addAction(QtGui.QIcon(IconDirectory + 'GitHub.png'), "GitHub Page", lambda: webbrowser.open('https://github.com/smeerten/ssnake/'))
self.githubAct.setToolTip('ssNake GitHub Page')
self.aboutAct = self.helpMenu.addAction(QtGui.QIcon(IconDirectory + 'about.png'), "&About", lambda: aboutWindow(self))
self.aboutAct.setToolTip('About Menu')
- self.helpActList = self.helpActList + [self.shiftconvAct, self.quadconvAct,
- self.nmrtableAct,self.githubAct,self.tutorialAct, self.aboutAct,self.basTutorialAct ]
+ self.helpActList = self.helpActList + [self.shiftconvAct, self.quadconvAct, self.nmrtableAct, self.githubAct,
+ self.tutorialAct, self.aboutAct, self.basTutorialAct]
# Extra event lists:
self.specOnlyList = [self.regridAct, self.csastaticAct, self.quadAct, self.quadCSAAct, self.czjzekAct]
- self.fidOnlyList = [self.relaxAct, self.diffusionAct,self.swapEchoAct]
- self.Only1DPlot = [self.snrAct, self.fwhmAct, self.massAct, self.intfitAct]
- self.notInArrayPlot = [self.userxAct,self.setrefAct,self.swapEchoAct,self.corOffsetAct,self.baselineAct,self.subAvgAct,
- self.refDeconvAct,self.intRegionAct,self.sumRegionAct,self.maxRegionAct,self.maxRegionAct,
- self.minRegionAct, self.maxposRegionAct,self.minposRegionAct,self.averageRegionAct,
- self.extractpartAct,self.matrixdelAct,self.normalizeAct,self.regridAct]
-
- def openRefMan(self):
- file = os.path.dirname(os.path.realpath(__file__)) + os.path.sep + '..' + os.path.sep + 'ReferenceManual.pdf'
- if sys.platform.startswith( 'linux' ):
- os.system("xdg-open " + '"' + file + '"')
- elif sys.platform.startswith( 'darwin' ):
- os.system("open " + '"' + file + '"')
- elif sys.platform.startswith( 'win' ):
- os.startfile(file)
-
- def openTutorial(self):
- path = os.path.dirname(os.path.realpath(__file__)) + os.path.sep + '..' + os.path.sep + '/Tutorial'
- if sys.platform.startswith( 'linux' ):
- os.system("xdg-open " + '"' + path + '"')
- elif sys.platform.startswith( 'darwin' ):
- os.system("open " + '"' + path + '"')
- elif sys.platform.startswith( 'win' ):
- os.startfile(path)
+ self.fidOnlyList = [self.relaxAct, self.diffusionAct, self.swapEchoAct]
+ self.Only1DPlot = [self.snrAct, self.fwhmAct, self.massAct, self.intfitAct]
+ self.notInArrayPlot = [self.userxAct, self.setrefAct, self.swapEchoAct, self.corOffsetAct, self.baselineAct, self.subAvgAct,
+ self.refDeconvAct, self.intRegionAct, self.sumRegionAct, self.maxRegionAct, self.maxRegionAct,
+ self.minRegionAct, self.maxposRegionAct, self.minposRegionAct, self.averageRegionAct,
+ self.extractpartAct, self.matrixdelAct, self.normalizeAct, self.regridAct]
def mainWindowCheck(self, transfer):
# checks if mainWindow exist to execute the function
@@ -987,7 +977,7 @@ def menuCheck(self):
self.noUndoAct.setChecked(True)
else:
self.noUndoAct.setChecked(False)
- if (len(self.mainWindow.masterData.shape()) < 2):
+ if len(self.mainWindow.masterData.shape()) < 2:
for i in self.multiDActions:
i.setEnabled(False)
else:
@@ -1079,12 +1069,12 @@ def askName(self, filePath=None, name=None):
name = 'spectrum' + str(count)
givenName, ok = QtWidgets.QInputDialog.getText(self, message, 'Name:', text=name)
if not ok:
- return
+ return None
while (givenName in self.workspaceNames) or givenName == '':
self.dispMsg("Workspace name '" + givenName + "' already exists")
givenName, ok = QtWidgets.QInputDialog.getText(self, message, 'Name:', text=name)
if not ok:
- return
+ return None
return givenName
def undo(self, *args):
@@ -1108,7 +1098,7 @@ def macroCreate(self):
givenName, ok = QtWidgets.QInputDialog.getText(self, 'Macro name', 'Name:', text=name)
if not ok:
return
- while (givenName in self.macros.keys()) or givenName is '':
+ while (givenName in self.macros.keys()) or (givenName == ''):
self.dispMsg("Macro name '" + givenName + "' already exists")
givenName, ok = QtWidgets.QInputDialog.getText(self, 'Macro name', 'Name:', text=name)
if not ok:
@@ -1202,7 +1192,7 @@ def loadMacro(self):
filename = filename[0]
if filename: # if not cancelled
self.lastLocation = os.path.dirname(filename) # Save used path
- if len(filename) == 0:
+ if not filename:
return
self.stopMacro()
count = 0
@@ -1211,7 +1201,7 @@ def loadMacro(self):
count += 1
name = 'macro' + str(count)
givenName, ok = QtWidgets.QInputDialog.getText(self, 'Macro name', 'Name:', text=name)
- while (givenName in self.macros.keys()) or givenName is '':
+ while (givenName in self.macros.keys()) or (givenName == ''):
if not ok:
return
self.dispMsg("Macro name '" + givenName + "' already exists")
@@ -1266,7 +1256,7 @@ def referenceRename(self, oldName):
givenName, ok = QtWidgets.QInputDialog.getText(self, 'Reference name', 'Name:', text=oldName)
if givenName == oldName or not ok:
return
- while (givenName in self.referenceName) or givenName is '':
+ while (givenName in self.referenceName) or (givenName == ''):
self.dispMsg('Name exists')
givenName, ok = QtWidgets.QInputDialog.getText(self, 'Reference name', 'Name:', text=oldName)
if not ok:
@@ -1291,8 +1281,7 @@ def referenceSave(self, name):
fileName = fileName[0]
if not fileName:
return
- else:
- self.lastLocation = os.path.dirname(fileName)
+ self.lastLocation = os.path.dirname(fileName)
reffreq = self.referenceValue[self.referenceName.index(name)]
with open(fileName, 'w') as f:
f.write(str(reffreq))
@@ -1303,7 +1292,7 @@ def referenceLoad(self):
filename = filename[0]
if filename: # if not cancelled
self.lastLocation = os.path.dirname(filename) # Save used path
- if len(filename) == 0:
+ if not filename:
return
name = os.path.basename(filename)
if name.endswith('.txt'): #If regular extension, name becomes filename - extension
@@ -1313,7 +1302,7 @@ def referenceLoad(self):
name = 'ref' + str(count)
count += 1
givenName, ok = QtWidgets.QInputDialog.getText(self, 'Reference name', 'Name:', text=name)
- while (givenName in self.macros.keys()) or givenName is '':
+ while (givenName in self.macros.keys()) or (givenName == ''):
if not ok:
return
self.dispMsg('Name exists')
@@ -1349,7 +1338,7 @@ def changeMainWindow(self, var):
self.workspaceNum = num
self.mainWindow = self.workspaces[num]
self.tabs.setCurrentIndex(num)
- self.updWorkspaceMenu(var)
+ self.updWorkspaceMenu()
self.menuCheck()
try:
if type(self.mainWindow.current) is views.CurrentMulti:
@@ -1373,7 +1362,7 @@ def stepWorkspace(self, step):
self.workspaceNum = self.workspaceNum % len(self.workspaces)
self.mainWindow = self.workspaces[self.workspaceNum]
self.tabs.setCurrentIndex(self.workspaceNum)
- self.updWorkspaceMenu(self.workspaceNames[self.workspaceNum])
+ self.updWorkspaceMenu()
self.menuCheck()
if type(self.mainWindow) is not SaveFigureWindow:
if type(self.mainWindow.current) is views.CurrentMulti:
@@ -1388,7 +1377,7 @@ def duplicateWorkspace(self, sliceOnly=False, *args):
data = copy.deepcopy(self.mainWindow.get_masterData())
if name is None:
return
- self.workspaces.append(Main1DWindow(self, data , self.mainWindow.get_current()))
+ self.workspaces.append(Main1DWindow(self, data, self.mainWindow.get_current()))
self.workspaces[-1].rename(name)
self.tabs.addTab(self.workspaces[-1], name)
self.workspaceNames.append(name)
@@ -1403,7 +1392,7 @@ def renameWorkspace(self, *args):
return
self.workspaceNames[self.workspaceNum] = name
self.tabs.setTabText(self.workspaceNum, name)
- self.updWorkspaceMenu(name)
+ self.updWorkspaceMenu()
self.workspaces[self.workspaceNum].rename(name)
def destroyWorkspace(self, num=None):
@@ -1426,14 +1415,14 @@ def destroyWorkspace(self, num=None):
self.workspaceNum = num - 1
if num < self.workspaceNum:
self.workspaceNum -= 1
- if len(self.workspaces) > 0:
+ if self.workspaces:
self.changeMainWindow(self.workspaceNames[self.workspaceNum])
else:
self.logo.show()
self.tabs.hide()
- self.updWorkspaceMenu(None)
+ self.updWorkspaceMenu()
- def updWorkspaceMenu(self, var):
+ def updWorkspaceMenu(self):
self.activemenu.clear()
for i in self.workspaceNames:
self.activemenu.addAction(i, lambda i=i: self.changeMainWindow(i))
@@ -1488,12 +1477,12 @@ def loadData(self, fileList):
for filePath in fileList:
if filePath: # if not cancelled
self.lastLocation = os.path.dirname(filePath) # Save used path
- if len(filePath) == 0:
+ if not filePath:
return
masterData = io.autoLoad(filePath)
if masterData is None:
return
- elif masterData == -1:
+ if masterData == -1:
dialog = AsciiLoadWindow(self, filePath)
if dialog.exec_():
if dialog.closed:
@@ -1648,7 +1637,7 @@ def createTempcalWindow(self):
def nmrTable(self):
import nmrTable
- nmrTable.PeriodicTable()
+ nmrTable.PeriodicTable()
def fileQuit(self):
self.close()
@@ -1758,7 +1747,7 @@ def menuCheck(self):
self.father.menuCheck()
def runMacro(self, macro, display=True):
- for i in range(len(macro)):
+ for i, _ in enumerate(macro):
iter1 = macro[i] # Do not loop over the macro list itself to prevent recursion if the running macro is also the one being recorded
self.addMacro(iter1)
try:
@@ -1956,9 +1945,8 @@ def autoPhaseAll(self, phaseNum):
def CorrectDigitalFilter(self):
if self.current.data.dFilter is None:
raise SsnakeException('Digital filter: no value defined')
- else:
- self.current.correctDFilter()
- self.menuCheck()
+ self.current.correctDFilter()
+ self.menuCheck()
def createRelaxWindow(self):
self.father.createFitWindow(fit.TabFittingWindow(self.father, self.father.mainWindow, 'relax'))
@@ -2053,6 +2041,16 @@ def plotContour(self):
self.updAllFrames()
self.menuCheck()
+ def plotColour2D(self):
+ if len(self.masterData.shape()) < 2:
+ raise SsnakeException("Data does not have enough dimensions")
+ tmpcurrent = views.CurrentColour2D(self, self.fig, self.canvas, self.masterData, self.current)
+ self.current.kill()
+ del self.current
+ self.current = tmpcurrent
+ self.updAllFrames()
+ self.menuCheck()
+
def plotMulti(self):
tmpcurrent = views.CurrentMulti(self, self.fig, self.canvas, self.masterData, self.current)
self.current.kill()
@@ -2096,7 +2094,7 @@ def clearUndo(self):
class SideFrame(QtWidgets.QScrollArea):
FITTING = False
-
+
def __init__(self, parent):
super(SideFrame, self).__init__(parent)
self.father = parent
@@ -2181,7 +2179,7 @@ def upd(self):
self.entries[num].setValue(current.locList[num])
if self.FITTING and num in current.axes:
self.entries[num].setDisabled(True)
- self.entries[num].valueChanged.connect(lambda event=None, num=num: self.getSlice(event, num))
+ self.entries[num].valueChanged.connect(lambda event, num=num: self.getSlice(num))
if type(current) is views.CurrentStacked or type(current) is views.CurrentArrayed:
if current.viewSettings["stackBegin"] is not None:
from2D = current.viewSettings["stackBegin"]
@@ -2220,68 +2218,69 @@ def upd(self):
self.spacingEntry.returnPressed.connect(self.setSpacing)
self.frame2.addWidget(self.spacingEntry, 8, 0)
if isinstance(current, (views.CurrentContour)):
- self.contourTypeGroup = QtWidgets.QGroupBox('Contour type:')
- self.contourTypeFrame = QtWidgets.QGridLayout()
- self.contourNumberLabel = wc.QLeftLabel("Number:", self)
- self.contourTypeFrame.addWidget(self.contourNumberLabel, 0, 0)
- self.numLEntry = wc.SsnakeSpinBox()
- self.numLEntry.setMaximum(100000)
- self.numLEntry.setMinimum(1)
- self.numLEntry.setToolTip(TOOLTIPS['contourNumber'])
- self.numLEntry.setValue(current.viewSettings["numLevels"])
- self.numLEntry.valueChanged.connect(self.setContour)
- self.contourTypeFrame.addWidget(self.numLEntry, 0, 1)
- self.contourTypeFrame.addWidget(wc.QLeftLabel("Sign:", self), 1, 0)
- self.contourSignEntry = QtWidgets.QComboBox()
- self.contourSignEntry.setToolTip(TOOLTIPS['contourSign'])
- self.contourSignEntry.addItems(['Both', '+ only', '- only'])
- self.contourSignEntry.setCurrentIndex(current.viewSettings["contourSign"])
- self.contourSignEntry.currentIndexChanged.connect(self.setContour)
- self.contourTypeFrame.addWidget(self.contourSignEntry, 1, 1)
- self.contourTypeLabel = wc.QLeftLabel("Type:", self)
- self.contourTypeFrame.addWidget(self.contourTypeLabel, 2, 0)
- self.contourTypeEntry = QtWidgets.QComboBox()
- self.contourTypeEntry.setToolTip(TOOLTIPS['contourType'])
- self.contourTypeEntry.addItems(['Linear', 'Multiplier'])
- self.contourTypeEntry.setCurrentIndex(current.viewSettings["contourType"])
- self.contourTypeEntry.currentIndexChanged.connect(self.setContour)
- self.contourTypeFrame.addWidget(self.contourTypeEntry, 2, 1)
- self.multiValueLabel = wc.QLeftLabel("Multiplier:", self)
- self.contourTypeFrame.addWidget(self.multiValueLabel, 3, 0)
- self.multiValue = wc.QLineEdit(current.viewSettings["multiValue"], self.setContour)
- self.multiValue.setToolTip(TOOLTIPS['contourMultiplier'])
- self.multiValue.setMaximumWidth(120)
- self.contourTypeFrame.addWidget(self.multiValue, 3, 1)
- if current.viewSettings["contourType"] != 1:
- self.multiValueLabel.hide()
- self.multiValue.hide()
- self.contourTypeGroup.setLayout(self.contourTypeFrame)
- self.frame2.addWidget(self.contourTypeGroup, 6, 0, 1, 3)
- # Contour limits
- self.contourLimitsGroup = QtWidgets.QGroupBox('Contour limits [%]:')
- self.contourLimitsFrame = QtWidgets.QGridLayout()
- self.maxLEntry = wc.QLineEdit(format(current.viewSettings["maxLevels"] * 100.0, '.7g'), self.setContour)
- self.maxLEntry.setMaximumWidth(120)
- self.maxLEntry.setToolTip(TOOLTIPS['contourMax'])
- self.contourLimitsFrame.addWidget(self.maxLEntry, 1, 1)
- self.minLEntry = wc.QLineEdit(format(current.viewSettings["minLevels"] * 100.0, '.7g'), self.setContour)
- self.minLEntry.setMaximumWidth(120)
- self.minLEntry.setToolTip(TOOLTIPS['contourMin'])
- self.contourLimitsFrame.addWidget(self.minLEntry, 2, 1)
- self.contourLimType = QtWidgets.QComboBox()
- self.contourLimType.addItems(['Current 2D', 'Full data'])
- self.contourLimType.setCurrentIndex(current.viewSettings["limitType"])
- self.contourLimType.setToolTip(TOOLTIPS['contourLimType'])
- self.contourLimType.currentIndexChanged.connect(self.setContour)
- self.contourLimitsFrame.addWidget(self.contourLimType, 0, 1)
- self.maxLabel = wc.QLeftLabel("Max:", self)
- self.minLabel = wc.QLeftLabel("Min:", self)
- self.relLabel = wc.QLeftLabel("Rel. to:", self)
- self.contourLimitsFrame.addWidget(self.relLabel, 0, 0)
- self.contourLimitsFrame.addWidget(self.maxLabel, 1, 0)
- self.contourLimitsFrame.addWidget(self.minLabel, 2, 0)
- self.contourLimitsGroup.setLayout(self.contourLimitsFrame)
- self.frame2.addWidget(self.contourLimitsGroup, 7, 0, 1, 3)
+ if type(current) is views.CurrentContour:
+ self.contourTypeGroup = QtWidgets.QGroupBox('Contour type:')
+ self.contourTypeFrame = QtWidgets.QGridLayout()
+ self.contourNumberLabel = wc.QLeftLabel("Number:", self)
+ self.contourTypeFrame.addWidget(self.contourNumberLabel, 0, 0)
+ self.numLEntry = wc.SsnakeSpinBox()
+ self.numLEntry.setMaximum(100000)
+ self.numLEntry.setMinimum(1)
+ self.numLEntry.setToolTip(TOOLTIPS['contourNumber'])
+ self.numLEntry.setValue(current.viewSettings["numLevels"])
+ self.numLEntry.valueChanged.connect(self.setContour)
+ self.contourTypeFrame.addWidget(self.numLEntry, 0, 1)
+ self.contourTypeFrame.addWidget(wc.QLeftLabel("Sign:", self), 1, 0)
+ self.contourSignEntry = QtWidgets.QComboBox()
+ self.contourSignEntry.setToolTip(TOOLTIPS['contourSign'])
+ self.contourSignEntry.addItems(['Both', '+ only', '- only'])
+ self.contourSignEntry.setCurrentIndex(current.viewSettings["contourSign"])
+ self.contourSignEntry.currentIndexChanged.connect(self.setContour)
+ self.contourTypeFrame.addWidget(self.contourSignEntry, 1, 1)
+ self.contourTypeLabel = wc.QLeftLabel("Type:", self)
+ self.contourTypeFrame.addWidget(self.contourTypeLabel, 2, 0)
+ self.contourTypeEntry = QtWidgets.QComboBox()
+ self.contourTypeEntry.setToolTip(TOOLTIPS['contourType'])
+ self.contourTypeEntry.addItems(['Linear', 'Multiplier'])
+ self.contourTypeEntry.setCurrentIndex(current.viewSettings["contourType"])
+ self.contourTypeEntry.currentIndexChanged.connect(self.setContour)
+ self.contourTypeFrame.addWidget(self.contourTypeEntry, 2, 1)
+ self.multiValueLabel = wc.QLeftLabel("Multiplier:", self)
+ self.contourTypeFrame.addWidget(self.multiValueLabel, 3, 0)
+ self.multiValue = wc.QLineEdit(current.viewSettings["multiValue"], self.setContour)
+ self.multiValue.setToolTip(TOOLTIPS['contourMultiplier'])
+ self.multiValue.setMaximumWidth(120)
+ self.contourTypeFrame.addWidget(self.multiValue, 3, 1)
+ if current.viewSettings["contourType"] != 1:
+ self.multiValueLabel.hide()
+ self.multiValue.hide()
+ self.contourTypeGroup.setLayout(self.contourTypeFrame)
+ self.frame2.addWidget(self.contourTypeGroup, 6, 0, 1, 3)
+ # Contour limits
+ self.contourLimitsGroup = QtWidgets.QGroupBox('Contour limits [%]:')
+ self.contourLimitsFrame = QtWidgets.QGridLayout()
+ self.maxLEntry = wc.QLineEdit(format(current.viewSettings["maxLevels"] * 100.0, '.7g'), self.setContour)
+ self.maxLEntry.setMaximumWidth(120)
+ self.maxLEntry.setToolTip(TOOLTIPS['contourMax'])
+ self.contourLimitsFrame.addWidget(self.maxLEntry, 1, 1)
+ self.minLEntry = wc.QLineEdit(format(current.viewSettings["minLevels"] * 100.0, '.7g'), self.setContour)
+ self.minLEntry.setMaximumWidth(120)
+ self.minLEntry.setToolTip(TOOLTIPS['contourMin'])
+ self.contourLimitsFrame.addWidget(self.minLEntry, 2, 1)
+ self.contourLimType = QtWidgets.QComboBox()
+ self.contourLimType.addItems(['Current 2D', 'Full data'])
+ self.contourLimType.setCurrentIndex(current.viewSettings["limitType"])
+ self.contourLimType.setToolTip(TOOLTIPS['contourLimType'])
+ self.contourLimType.currentIndexChanged.connect(self.setContour)
+ self.contourLimitsFrame.addWidget(self.contourLimType, 0, 1)
+ self.maxLabel = wc.QLeftLabel("Max:", self)
+ self.minLabel = wc.QLeftLabel("Min:", self)
+ self.relLabel = wc.QLeftLabel("Rel. to:", self)
+ self.contourLimitsFrame.addWidget(self.relLabel, 0, 0)
+ self.contourLimitsFrame.addWidget(self.maxLabel, 1, 0)
+ self.contourLimitsFrame.addWidget(self.minLabel, 2, 0)
+ self.contourLimitsGroup.setLayout(self.contourLimitsFrame)
+ self.frame2.addWidget(self.contourLimitsGroup, 7, 0, 1, 3)
# Projections
self.contourProjGroup = QtWidgets.QGroupBox('Projections:')
self.contourProjFrame = QtWidgets.QGridLayout()
@@ -2472,7 +2471,7 @@ def upd(self):
buttons1 = []
self.extraButtons1.append(buttons1)
self.extraButtons1Group.append(QtWidgets.QButtonGroup(self))
- self.extraButtons1Group[i].buttonClicked.connect(lambda: self.setExtraAxes(True))
+ self.extraButtons1Group[i].buttonClicked.connect(self.setExtraAxes)
if current.viewSettings["extraData"][i].ndim() > 1:
for num in range(current.viewSettings["extraData"][i].ndim()):
buttons1.append(QtWidgets.QRadioButton(''))
@@ -2484,7 +2483,7 @@ def upd(self):
entries[-1].setToolTip(TOOLTIPS['sideFrameDimensionSlice'])
frame.addWidget(entries[num], num * 3 + 6, 1)
entries[num].setValue(current.viewSettings["extraLoc"][i][num])
- entries[num].valueChanged.connect(lambda event=None, num=num, i=i: self.getExtraSlice(event, num, i))
+ entries[num].valueChanged.connect(lambda event, num=num, i=i: self.getExtraSlice(num, i))
self.extraButtons1Group[i].button(current.viewSettings["extraAxes"][i][-1]).toggle()
iter1 += 1
addButton = QtWidgets.QPushButton("Add plot", self)
@@ -2511,19 +2510,19 @@ def scrollSpacing(self, var):
self.spacingEntry.setText('%#.3g' % var)
def setSpacing(self, *args):
- var = safeEval(self.spacingEntry.text(), length=self.father.current.len(), type='FI')
+ var = safeEval(self.spacingEntry.text(), length=self.father.current.len(), Type='FI')
self.spacingEntry.setText('%#.3g' % var)
self.father.current.setSpacing(var)
def setContour(self, *args):
var1 = self.numLEntry.value()
- maxC = safeEval(self.maxLEntry.text(), length=self.father.current.len(), type='FI')
+ maxC = safeEval(self.maxLEntry.text(), length=self.father.current.len(), Type='FI')
if maxC is None:
maxC = self.father.current.viewSettings["maxLevels"] * 100
self.father.father.dispMsg('Invalid value for contour maximum')
else:
maxC = abs(float(maxC))
- minC = safeEval(self.minLEntry.text(), length=self.father.current.len(), type='FI')
+ minC = safeEval(self.minLEntry.text(), length=self.father.current.len(), Type='FI')
if minC is None:
minC = self.father.current.viewSettings["minLevels"] * 100
self.father.father.dispMsg('Invalid value for contour minimum')
@@ -2541,7 +2540,7 @@ def setContour(self, *args):
else:
self.multiValue.show()
self.multiValueLabel.show()
- multi = safeEval(self.multiValue.text(), length=self.father.current.len(), type='FI')
+ multi = safeEval(self.multiValue.text(), length=self.father.current.len(), Type='FI')
if multi is None:
multi = self.father.current.viewSettings["multiValue"]
self.father.father.dispMsg('Invalid value for contour multiplier')
@@ -2552,19 +2551,19 @@ def setContour(self, *args):
self.father.current.setLevels(var1, maxC / 100.0, minC / 100.0, limitType, cSign, cType, multi)
def changeProj(self, pType, direc):
- if pType is 4:
- if direc is 1:
+ if pType == 4:
+ if direc == 1:
self.projTraceTop.show()
else:
self.projTraceRight.show()
else:
self.selectTraceButton.hide()
- if direc is 1:
+ if direc == 1:
self.projTraceTop.hide()
else:
self.projTraceRight.hide()
self.father.current.setProjType(pType, direc)
- if (self.father.current.viewSettings["projTop"] is 4) or (self.father.current.viewSettings["projRight"] is 4):
+ if (self.father.current.viewSettings["projTop"] == 4) or (self.father.current.viewSettings["projRight"] == 4):
self.selectTraceButton.show()
else:
self.selectTraceButton.hide()
@@ -2591,7 +2590,7 @@ def pickedTraces(self, pos):
self.projTraceTop.setValue(pos[3])
if self.father.current.viewSettings["projRight"] == 4 and pos[3] != self.projTraceRight.value():
self.projTraceRight.setValue(pos[0])
-
+
def changeRanges(self):
check = self.rangeCheckbox.isChecked()
ranges = [self.projTopRangeMax.value(), self.projTopRangeMin.value(), self.projRightRangeMax.value(), self.projRightRangeMin.value()]
@@ -2639,7 +2638,7 @@ def setAxes(self, first=True):
self.father.current.setProjTraces(self.projTraceTop.value(), 1)
self.father.current.setProjTraces(self.projTraceRight.value(), 0)
#Flip diagonal multiplier:
- inp = safeEval(self.diagonalEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.diagonalEntry.text(), length=self.father.current.len(), Type='FI')
if inp is not None:
self.father.current.viewSettings["diagonalMult"] = 1.0 / inp
#Make sure the bottom frame nicely inverts the axis units
@@ -2659,14 +2658,13 @@ def setAxes(self, first=True):
tmp2 = freq2
else:
tmp2 = time2
- self.father.bottomframe.changeAxis(tmp2, update = False)
- self.father.bottomframe.changeAxis2(tmp1, update = False)
+ self.father.bottomframe.changeAxis(tmp2, update=False)
+ self.father.bottomframe.changeAxis2(tmp1, update=False)
self.buttons2Group.button(axes2).toggle()
- self.getSlice(None, axes, True)
+ self.getSlice(axes, True)
self.upd()
- # self.father.menuCheck()
- def getSlice(self, event, entryNum, button=False):
+ def getSlice(self, entryNum, button=False):
axisChange = False
if button:
dimNum = entryNum
@@ -2701,13 +2699,13 @@ def getSlice(self, event, entryNum, button=False):
self.father.menuCheck()
self.upd()
- def setExtraAxes(self, first=True):
+ def setExtraAxes(self, *args):
for i in range(len(self.extraButtons1Group)):
axes = self.extraButtons1Group[i].checkedId()
- self.getExtraSlice(None, axes, i, True)
+ self.getExtraSlice(axes, i, True)
self.father.current.showFid()
- def getExtraSlice(self, event, entryNum, entryi, button=False):
+ def getExtraSlice(self, entryNum, entryi, button=False):
length = self.father.current.viewSettings["extraData"][entryi].ndim()
if button:
dimNum = entryNum
@@ -2741,7 +2739,7 @@ def switchDiagonal(self, val):
self.father.current.setDiagonal(bool(val))
def setDiagonal(self):
- inp = safeEval(self.diagonalEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.diagonalEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
inp = self.father.current.viewSettings["diagonalMult"]
self.father.father.dispMsg('Invalid value for diagonal multiplier')
@@ -2920,8 +2918,8 @@ def changeSpec(self):
self.father.menuCheck()
def changeFreq(self):
- freq = safeEval(self.freqEntry.text(), length=self.father.current.len(), type='FI')
- sw = safeEval(self.swEntry.text(), length=self.father.current.len(), type='FI')
+ freq = safeEval(self.freqEntry.text(), length=self.father.current.len(), Type='FI')
+ sw = safeEval(self.swEntry.text(), length=self.father.current.len(), Type='FI')
if sw is None:
self.father.father.dispMsg('Invalid sweepwidth')
elif sw == 0.0:
@@ -3121,16 +3119,16 @@ def __init__(self, parent, file):
okButton = QtWidgets.QPushButton("&Ok")
okButton.clicked.connect(self.applyAndClose)
box = QtWidgets.QDialogButtonBox()
- box.addButton(cancelButton,QtWidgets.QDialogButtonBox.RejectRole)
- box.addButton(okButton,QtWidgets.QDialogButtonBox.AcceptRole)
- grid.addWidget(box, 13, 0,1,2)
+ box.addButton(cancelButton, QtWidgets.QDialogButtonBox.RejectRole)
+ box.addButton(okButton, QtWidgets.QDialogButtonBox.AcceptRole)
+ grid.addWidget(box, 13, 0, 1, 2)
self.show()
self.setFixedSize(self.size())
self.checkType(file)
def checkDatOrder(self):
tmp = self.dataOrders[self.datOrderBox.currentIndex()]
- if tmp == 'RI' or tmp == 'R':
+ if tmp in ('RI', 'R'):
self.swLabel.show()
self.swEntry.show()
else:
@@ -3166,7 +3164,7 @@ def applyAndClose(self):
self.dataOrder = self.dataOrders[self.datOrderBox.currentIndex()]
self.delim = self.delimiters[self.datDelimBox.currentIndex()]
if self.dataOrder == 'RI' or self.dataOrder == 'R':
- self.sw = safeEval(self.swEntry.text(), type='FI')
+ self.sw = safeEval(self.swEntry.text(), Type='FI')
if self.sw == 0 or self.sw is None:
raise SsnakeException('Spectral Width input is not valid')
self.dataDimension = self.numDims.value()
@@ -3188,7 +3186,6 @@ def __init__(self, parent):
self.setWindowFlags(QtCore.Qt.Window | QtCore.Qt.Tool | QtCore.Qt.WindowContextHelpButtonHint)
self.setWindowTitle("Workspace Info")
grid = QtWidgets.QGridLayout(self)
-
workGroup = QtWidgets.QGroupBox('Data:')
workFrame = QtWidgets.QGridLayout()
workGroup.setLayout(workFrame)
@@ -3218,20 +3215,17 @@ def __init__(self, parent):
workFrame.addWidget(QtWidgets.QLabel('Type:'), 7, 0)
workFrame.addWidget(QtWidgets.QLabel('Complex:'), 8, 0)
workFrame.addWidget(QtWidgets.QLabel('Whole Echo:'), 9, 0)
- grid.addWidget(workGroup, 0, 0,1,3)
-
-
+ grid.addWidget(workGroup, 0, 0, 1, 3)
metaGroup = QtWidgets.QGroupBox('Metadata:')
metaFrame = QtWidgets.QGridLayout()
metaGroup.setLayout(metaFrame)
for pos, key in enumerate(self.father.masterData.metaData):
metaFrame.addWidget(QtWidgets.QLabel(key), pos, 0)
metaFrame.addWidget(wc.QSelectLabel(self.father.masterData.metaData[key]), pos, 1)
- grid.addWidget(metaGroup, 1, 0,1,3)
-
+ grid.addWidget(metaGroup, 1, 0, 1, 3)
okButton = QtWidgets.QPushButton("&Close")
okButton.clicked.connect(self.closeEvent)
- grid.addWidget(okButton, 2, 1 )
+ grid.addWidget(okButton, 2, 1)
self.show()
self.setFixedSize(self.size())
@@ -3241,7 +3235,7 @@ def closeEvent(self, *args):
self.deleteLater()
#################################################################################
-class PhaseWindow(wc.ToolWindows):
+class PhaseWindow(wc.ToolWindow):
NAME = "Phasing"
SINGLESLICE = True
@@ -3308,7 +3302,7 @@ def __init__(self, parent):
self.firstOrderGroup.setLayout(self.firstOrderFrame)
self.grid.addWidget(self.firstOrderGroup, 1, 0, 1, 3)
- def setModifierTexts(self,event):
+ def setModifierTexts(self, event):
sign = u"\u00D7"
if event.modifiers() & QtCore.Qt.AltModifier:
sign = '/'
@@ -3340,7 +3334,7 @@ def setZeroOrder(self, value, *args):
self.father.current.setPhaseInter(np.pi * self.zeroVal / 180.0, np.pi * self.firstVal / 180.0)
def inputZeroOrder(self, *args):
- inp = safeEval(self.zeroEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.zeroEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException('Phasing: zero order value input is not valid!')
self.zeroVal = np.mod(inp + 180, 360) - 180
@@ -3364,7 +3358,7 @@ def setFirstOrder(self, value, *args):
self.father.current.setPhaseInter(np.pi * self.zeroVal / 180.0, np.pi * self.firstVal / 180.0)
def inputFirstOrder(self, *args):
- value = safeEval(self.firstEntry.text(), length=self.father.current.len(), type='FI')
+ value = safeEval(self.firstEntry.text(), length=self.father.current.len(), Type='FI')
if value is None:
raise SsnakeException('Phasing: first order value input is not valid!')
newZero = (self.zeroVal - (value - self.firstVal) * self.pivotVal / self.father.current.sw())
@@ -3408,12 +3402,12 @@ def stepPhase(self, phase0, phase1):
phase0 = step * phase0
phase1 = step * phase1
- inp = safeEval(self.zeroEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.zeroEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException('Phasing: zero order value input is not valid!')
inp += phase0 * self.PHASE0STEP
self.zeroVal = np.mod(inp + 180, 360) - 180
- value = safeEval(self.firstEntry.text(), length=self.father.current.len(), type='FI')
+ value = safeEval(self.firstEntry.text(), length=self.father.current.len(), Type='FI')
if value is None:
raise SsnakeException('Phasing: first order value input is not valid!')
value += phase1 * self.PHASE1STEP
@@ -3432,7 +3426,7 @@ def stepPhase(self, phase0, phase1):
self.father.current.setPhaseInter(np.pi * self.zeroVal / 180.0, np.pi * self.firstVal / 180.0)
def inputRef(self, *args):
- Val = safeEval(self.refEntry.text(), length=self.father.current.len(), type='FI')
+ Val = safeEval(self.refEntry.text(), length=self.father.current.len(), Type='FI')
if Val is None:
raise SsnakeException('Phasing: pivot input is not valid!')
self.pivotVal = Val
@@ -3456,7 +3450,7 @@ def applyFunc(self):
################################################################
-class ApodWindow(wc.ToolWindows):
+class ApodWindow(wc.ToolWindow):
RESOLUTION = 10000
NAME = "Apodize"
@@ -3466,7 +3460,7 @@ def __init__(self, parent):
super(ApodWindow, self).__init__(parent)
self.entries = {}
self.ticks = {}
- boldFont=QtGui.QFont()
+ boldFont = QtGui.QFont()
boldFont.setBold(True)
self.maximum = 100.0 * self.father.current.sw() / (self.father.current.len())
self.lbstep = 1.0
@@ -3493,7 +3487,7 @@ def __init__(self, parent):
self.lorFrame.addWidget(self.rightLor, 1, 2)
self.lorScale = wc.SsnakeSlider(QtCore.Qt.Horizontal)
self.lorScale.setRange(0, self.RESOLUTION)
- self.lorScale.valueChanged.connect(lambda x: self.setLorGauss(x,'lor'))
+ self.lorScale.valueChanged.connect(lambda x: self.setLorGauss(x, 'lor'))
self.lorFrame.addWidget(self.lorScale, 2, 0, 1, 3)
self.lorMax = 100.0 * self.father.current.sw() / (self.father.current.len())
self.lorGroup.setLayout(self.lorFrame)
@@ -3520,7 +3514,7 @@ def __init__(self, parent):
self.gaussFrame.addWidget(self.rightGauss, 4, 2)
self.gaussScale = wc.SsnakeSlider(QtCore.Qt.Horizontal)
self.gaussScale.setRange(0, self.RESOLUTION)
- self.gaussScale.valueChanged.connect(lambda x: self.setLorGauss(x,'gauss'))
+ self.gaussScale.valueChanged.connect(lambda x: self.setLorGauss(x, 'gauss'))
self.gaussFrame.addWidget(self.gaussScale, 5, 0, 1, 3)
self.gaussMax = 100.0 * self.father.current.sw() / (self.father.current.len())
self.gaussGroup.setLayout(self.gaussFrame)
@@ -3590,7 +3584,7 @@ def __init__(self, parent):
self.shiftFrame.addWidget(QtWidgets.QWidget(), 1, 1)
shiftEntry.setMinimumSize(widthHint)
shiftEntry.setEnabled(False)
- self.entries['shift'] = [shiftEntry,shiftLabel]
+ self.entries['shift'] = [shiftEntry, shiftLabel]
self.shiftFrame.addWidget(shiftEntry, 1, 2)
self.shiftGroup.setLayout(self.shiftFrame)
self.shiftFrame.setColumnStretch(1, 1)
@@ -3638,11 +3632,11 @@ def __init__(self, parent):
self.shiftingFrame.addWidget(shiftingAxisLabel, 3, 0)
self.shiftingFrame.addWidget(QtWidgets.QWidget(), 1, 1)
self.shiftingFrame.setColumnStretch(1, 1)
- self.entries['shifting'] = [self.shiftingDropdown,shiftingTypeLabel,self.shiftingEntry,shiftingValueLabel,self.shiftingAxis,shiftingAxisLabel]
+ self.entries['shifting'] = [self.shiftingDropdown, shiftingTypeLabel, self.shiftingEntry, shiftingValueLabel, self.shiftingAxis, shiftingAxisLabel]
self.shiftingGroup.setLayout(self.shiftingFrame)
self.grid.addWidget(self.shiftingGroup, 5, 0, 1, 3)
- def setModifierTexts(self,event):
+ def setModifierTexts(self, event):
sign = u"\u00D7"
if event.modifiers() & QtCore.Qt.AltModifier:
sign = '/'
@@ -3667,7 +3661,7 @@ def keyPressEvent(self, event):
def keyReleaseEvent(self, event):
self.setModifierTexts(event)
- def dropdownChanged(self,update = True):
+ def dropdownChanged(self, update=True):
index = self.shiftingDropdown.currentIndex()
if index == 0:
self.shiftingEntry.setEnabled(True)
@@ -3686,9 +3680,9 @@ def checkEval(self, key):
elem.setEnabled(False)
if self.father.current.data.ndim() > 1:
if self.ticks['shifting'].isChecked():
- self.dropdownChanged(update = False) #Check dropdown state
- if key == 'lor' or key == 'gauss': # for lorentzian and gaussian
- if safeEval(self.entries[key][0].text(), length=self.father.current.len(), type='FI') != 0.0: # only update if value was not zero
+ self.dropdownChanged(update=False) #Check dropdown state
+ if key in ('lor', 'gauss'): # for lorentzian and gaussian
+ if safeEval(self.entries[key][0].text(), length=self.father.current.len(), Type='FI') != 0.0: # only update if value was not zero
self.apodPreview()
else:
self.apodPreview()
@@ -3739,41 +3733,41 @@ def checkInput(self):
shifting = 0.0
shiftingAxis = None
if self.ticks['lor'].isChecked():
- lor = safeEval(self.entries['lor'][0].text(), length=self.father.current.len(), type='FI')
+ lor = safeEval(self.entries['lor'][0].text(), length=self.father.current.len(), Type='FI')
if lor is None:
self.father.current.showFid()
raise SsnakeException('Apodize: Lorentzian value is not valid!')
self.lorScale.setValue(round(lor * self.RESOLUTION / self.maximum))
if self.ticks['gauss'].isChecked():
- gauss = safeEval(self.entries['gauss'][0].text(), length=self.father.current.len(), type='FI')
+ gauss = safeEval(self.entries['gauss'][0].text(), length=self.father.current.len(), Type='FI')
if gauss is None:
self.father.current.showFid()
raise SsnakeException('Apodize: Gaussian value is not valid!')
self.gaussScale.setValue(round(gauss * self.RESOLUTION / self.maximum))
if self.ticks['cos2'].isChecked():
- cos2 = safeEval(self.entries['cos2'][0].text(), length=self.father.current.len(), type='FI')
+ cos2 = safeEval(self.entries['cos2'][0].text(), length=self.father.current.len(), Type='FI')
if cos2 is None:
self.father.current.showFid()
raise SsnakeException('Apodize: cos^2 frequency value is not valid!')
if self.ticks['cos2'].isChecked():
- cos2Ph = safeEval(self.entries['cos2'][2].text(), length=self.father.current.len(), type='FI')
+ cos2Ph = safeEval(self.entries['cos2'][2].text(), length=self.father.current.len(), Type='FI')
if cos2Ph is None:
self.father.current.showFid()
raise SsnakeException('Apodize: cos^2 phase value is not valid!')
if self.ticks['hamming'].isChecked():
- hamming = safeEval(self.entries['hamming'][1].text(), length=self.father.current.len(), type='FI')
+ hamming = safeEval(self.entries['hamming'][1].text(), length=self.father.current.len(), Type='FI')
if hamming is None:
self.father.current.showFid()
raise SsnakeException('Apodize: Hamming value is not valid!')
if self.ticks['shift'].isChecked():
- shift = safeEval(self.entries['shift'][0].text(), length=self.father.current.len(), type='FI')
+ shift = safeEval(self.entries['shift'][0].text(), length=self.father.current.len(), Type='FI')
if shift is None:
self.father.current.showFid()
raise SsnakeException('Apodize: Shift value is not valid!')
if self.father.current.data.ndim() > 1:
if self.ticks['shifting'].isChecked():
if self.father.current.data.ndim() > 1:
- shifting = safeEval(self.shiftingEntry.text(), length=self.father.current.len(), type='FI')
+ shifting = safeEval(self.shiftingEntry.text(), length=self.father.current.len(), Type='FI')
if shifting is None:
self.father.current.showFid()
raise SsnakeException('Apodize: Shifting value is not valid!')
@@ -3788,7 +3782,7 @@ def applyFunc(self):
#######################################################################################
-class SizeWindow(wc.ToolWindows):
+class SizeWindow(wc.ToolWindow):
NAME = "Set size"
@@ -3825,7 +3819,7 @@ def __init__(self, parent):
self.father.current.peakPick = True
def stepSize(self, forward):
- inp = safeEval(self.sizeEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.sizeEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException('Sizing: \'Size\' input is not valid')
inp = int(round(inp))
@@ -3841,14 +3835,14 @@ def stepSize(self, forward):
self.sizePreview()
def sizePreview(self, *args):
- inp = safeEval(self.sizeEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.sizeEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException('Sizing: \'Size\' input is not valid')
self.sizeVal = int(round(inp))
if self.sizeVal < 1:
raise SsnakeException('Sizing: \'Size\' cannot be below 1')
self.sizeEntry.setText(str(self.sizeVal))
- inp = safeEval(self.posEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.posEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException('Sizing: \'Offset\' input is not valid')
self.posVal = int(round(inp))
@@ -3858,13 +3852,13 @@ def sizePreview(self, *args):
self.father.current.resizePreview(self.sizeVal, self.posVal)
def applyFunc(self):
- inp = safeEval(self.sizeEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.sizeEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException('Sizing: \'Size\' input is not valid')
self.sizeVal = int(round(inp))
if self.sizeVal < 1:
raise SsnakeException('Sizing: \'Size\' cannot be below 1')
- inp = safeEval(self.posEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.posEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException('Sizing: \'Offset\' input is not valid')
self.posVal = int(round(inp))
@@ -3882,7 +3876,7 @@ def picked(self, pos):
##########################################################################################
-class SwapEchoWindow(wc.ToolWindows):
+class SwapEchoWindow(wc.ToolWindow):
NAME = "Swap echo"
@@ -3896,7 +3890,7 @@ def __init__(self, parent):
self.father.current.peakPick = True
def swapEchoPreview(self, *args):
- inp = safeEval(self.posEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.posEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("Swap echo: not a valid index")
self.posVal = int(round(inp))
@@ -3907,7 +3901,7 @@ def swapEchoPreview(self, *args):
def applyFunc(self):
self.father.current.peakPickReset()
- inp = safeEval(self.posEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.posEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("Swap echo: not a valid index")
self.posVal = int(round(inp))
@@ -3925,7 +3919,7 @@ def picked(self, pos):
###########################################################################
-class LPSVDWindow(wc.ToolWindows):
+class LPSVDWindow(wc.ToolWindow):
NAME = "LPSVD"
@@ -3953,13 +3947,13 @@ def __init__(self, parent):
self.grid.addWidget(self.nPredictEntry, 8, 0)
def applyFunc(self):
- analPoints = safeEval(self.aPointsEntry.text(), length=self.father.current.len(), type='FI')
+ analPoints = safeEval(self.aPointsEntry.text(), length=self.father.current.len(), Type='FI')
if analPoints is None:
raise SsnakeException('LPSVD: Number of points for analysis is not valid')
- numberFreq = safeEval(self.nFreqEntry.text(), length=self.father.current.len(), type='FI')
+ numberFreq = safeEval(self.nFreqEntry.text(), length=self.father.current.len(), Type='FI')
if numberFreq is None:
raise SsnakeException('LPSVD: Number of frequencies is not valid')
- predictPoints = safeEval(self.nPredictEntry.text(), length=self.father.current.len(), type='FI')
+ predictPoints = safeEval(self.nPredictEntry.text(), length=self.father.current.len(), Type='FI')
if predictPoints is None:
raise SsnakeException('LPSVD: Number of points to predict is not valid')
if analPoints > self.father.current.len():
@@ -3975,13 +3969,12 @@ def applyFunc(self):
###########################################################################
-class ScaleSWWindow(wc.ToolWindows):
+class ScaleSWWindow(wc.ToolWindow):
NAME = "Scale SW"
def __init__(self, parent):
super(ScaleSWWindow, self).__init__(parent)
- options = list(map(str, range(1, self.father.masterData.ndim() + 1)))
self.grid.addWidget(wc.QLabel("Scale Factor:"), 0, 0)
self.scaleDropdown = QtWidgets.QComboBox()
self.scaleDropdown.addItems(['User Defined', 'Spin 3/2, -3Q (9/34)', 'Spin 5/2, 3Q (-12/17)', 'Spin 5/2, -5Q (12/85)', 'Spin 7/2, 3Q (-45/34)',
@@ -3997,7 +3990,7 @@ def dropdownChanged(self):
self.scaleEntry.setText("%.9f" % self.scaleList[index])
def applyFunc(self):
- scale = safeEval(self.scaleEntry.text(), length=self.father.current.len(), type='FI')
+ scale = safeEval(self.scaleEntry.text(), length=self.father.current.len(), Type='FI')
if scale is None:
raise SsnakeException("Scale SW: Factor not a valid value")
self.father.current.scaleSw(scale)
@@ -4005,7 +3998,7 @@ def applyFunc(self):
###########################################################################
-class ShiftDataWindow(wc.ToolWindows):
+class ShiftDataWindow(wc.ToolWindow):
NAME = "Shifting data"
SINGLESLICE = True
@@ -4027,40 +4020,39 @@ def __init__(self, parent):
self.grid.addWidget(rightShift, 1, 2)
def stepUpShift(self, *args):
- inp = safeEval(self.shiftEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.shiftEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("Shift data: shift value not valid")
self.shiftVal = int(round(inp))
- shift = +1
+ shift = 1
if QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ControlModifier and QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ShiftModifier:
- shift *= +1000
+ shift *= 1000
elif QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ControlModifier:
- shift *= +10
+ shift *= 10
elif QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ShiftModifier:
- shift *= +100
+ shift *= 100
self.shiftVal = self.shiftVal + shift
self.shiftEntry.setText(str(self.shiftVal))
self.shiftPreview()
def stepDownShift(self, *args):
- inp = safeEval(self.shiftEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.shiftEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("Shift data: shift value not valid")
self.shiftVal = int(round(inp))
- shift = -1
+ shift = -1
if QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ControlModifier and QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ShiftModifier:
- shift *= +1000
+ shift *= 1000
elif QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ControlModifier:
- shift *= +10
+ shift *= 10
elif QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ShiftModifier:
- shift *= +100
-
+ shift *= 100
self.shiftVal = self.shiftVal + shift
self.shiftEntry.setText(str(self.shiftVal))
self.shiftPreview()
def shiftPreview(self, *args):
- inp = safeEval(self.shiftEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.shiftEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("Shift data: shift value not valid")
self.shiftVal = int(round(inp))
@@ -4068,7 +4060,7 @@ def shiftPreview(self, *args):
self.father.current.shiftPreview(self.shiftVal)
def applyFunc(self):
- inp = safeEval(self.shiftEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.shiftEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("Shift data: shift value not valid")
shift = int(round(inp))
@@ -4076,7 +4068,7 @@ def applyFunc(self):
###########################################################################
-class RollDataWindow(wc.ToolWindows):
+class RollDataWindow(wc.ToolWindow):
NAME = "Roll data"
SINGLESLICE = True
@@ -4098,39 +4090,39 @@ def __init__(self, parent):
self.grid.addWidget(rightShift, 1, 2)
def stepUpShift(self, *args):
- inp = safeEval(self.shiftEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.shiftEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("Roll data: roll value not valid")
self.shiftVal = inp
- shift = +1
+ shift = 1
if QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ControlModifier and QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ShiftModifier:
- shift *= +1000
+ shift *= 1000
elif QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ControlModifier:
- shift *= +10
+ shift *= 10
elif QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ShiftModifier:
- shift *= +100
+ shift *= 100
self.shiftVal = self.shiftVal + shift
self.shiftEntry.setText(str(self.shiftVal))
self.rollPreview()
def stepDownShift(self, *args):
- inp = safeEval(self.shiftEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.shiftEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("Roll data: roll value not valid")
self.shiftVal = inp
- shift = -1
+ shift = -1
if QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ControlModifier and QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ShiftModifier:
- shift *= +1000
+ shift *= 1000
elif QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ControlModifier:
- shift *= +10
+ shift *= 10
elif QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ShiftModifier:
- shift *= +100
+ shift *= 100
self.shiftVal = self.shiftVal + shift
self.shiftEntry.setText(str(self.shiftVal))
self.rollPreview()
def rollPreview(self, *args):
- inp = safeEval(self.shiftEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.shiftEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("Roll data: roll value not valid")
self.shiftVal = inp
@@ -4138,7 +4130,7 @@ def rollPreview(self, *args):
self.father.current.rollPreview(self.shiftVal)
def applyFunc(self):
- inp = safeEval(self.shiftEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.shiftEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("Roll data: roll value not valid")
shift = inp
@@ -4147,7 +4139,7 @@ def applyFunc(self):
#############################################################
-class DCWindow(wc.ToolWindows):
+class DCWindow(wc.ToolWindow):
NAME = "Offset correction"
SINGLESLICE = True
@@ -4156,10 +4148,10 @@ def __init__(self, parent):
super(DCWindow, self).__init__(parent)
self.startVal = int(round(0.8 * parent.current.len()))
self.endVal = parent.current.len()
- self.grid.addWidget(wc.QLabel("Start point:"), 0, 0)
+ self.grid.addWidget(wc.QLabel("Start index:"), 0, 0)
self.startEntry = wc.QLineEdit(self.startVal, self.offsetPreview)
self.grid.addWidget(self.startEntry, 1, 0)
- self.grid.addWidget(wc.QLabel("End point:"), 2, 0)
+ self.grid.addWidget(wc.QLabel("End index:"), 2, 0)
self.endEntry = wc.QLineEdit(self.endVal, self.offsetPreview)
self.grid.addWidget(self.endEntry, 3, 0)
self.grid.addWidget(wc.QLabel("Offset:"), 4, 0)
@@ -4172,7 +4164,7 @@ def __init__(self, parent):
def picked(self, pos, second=False):
dataLength = self.father.current.len()
if second:
- inp = safeEval(self.startEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.startEntry.text(), length=self.father.current.len(), Type='FI')
if inp is not None:
self.startVal = int(round(inp))
if self.startVal < 0:
@@ -4192,7 +4184,7 @@ def picked(self, pos, second=False):
self.father.current.peakPick = True
else:
self.startEntry.setText(str(pos[0]))
- inp = safeEval(self.endEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.endEntry.text(), length=self.father.current.len(), Type='FI')
if inp is not None:
self.endVal = int(round(inp))
if self.endVal < 0:
@@ -4205,18 +4197,18 @@ def picked(self, pos, second=False):
self.offsetEntry.setText('{:.2e}'.format(val))
else:
self.offsetEntry.setText('')
- self.father.current.peakPickFunc = lambda pos, self= self: self.picked(pos, True)
+ self.father.current.peakPickFunc = lambda pos, self=self: self.picked(pos, True)
self.father.current.peakPick = True
def offsetPreview(self, inserted=False):
if inserted:
- dcVal = safeEval(self.offsetEntry.text(), length=self.father.current.len(), type='C')
+ dcVal = safeEval(self.offsetEntry.text(), length=self.father.current.len(), Type='C')
if dcVal is None:
raise SsnakeException("Offset correction: offset value not valid")
self.father.current.dcOffset(dcVal)
else:
dataLength = self.father.current.len()
- inp = safeEval(self.startEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.startEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("Offset correction: start value not valid")
self.startVal = int(round(inp))
@@ -4225,7 +4217,7 @@ def offsetPreview(self, inserted=False):
elif self.startVal > dataLength:
self.startVal = dataLength
self.startEntry.setText(str(self.startVal))
- inp = safeEval(self.endEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.endEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("Offset correction: end value not valid")
self.endVal = int(round(inp))
@@ -4239,7 +4231,7 @@ def offsetPreview(self, inserted=False):
self.father.current.dcOffset(val)
def applyFunc(self):
- inp = safeEval(self.offsetEntry.text(), length=self.father.current.len(), type='C')
+ inp = safeEval(self.offsetEntry.text(), length=self.father.current.len(), Type='C')
if inp is None:
raise SsnakeException("Offset correction: offset value not valid")
self.father.current.peakPickReset()
@@ -4248,7 +4240,7 @@ def applyFunc(self):
#############################################################
-class BaselineWindow(wc.ToolWindows):
+class BaselineWindow(wc.ToolWindow):
NAME = "Baseline correction"
SINGLESLICE = True
@@ -4303,7 +4295,7 @@ def closeEvent(self, *args):
def applyFunc(self):
inp = self.degreeEntry.value()
if self.allFitButton.isChecked():
- self.father.current.baselineCorrectionAll(inp, self.removeList, self.singleSlice.isChecked(), invert=self.invertButton.isChecked())
+ self.father.current.baselineCorrectionAll(inp, self.removeList, invert=self.invertButton.isChecked())
else:
self.father.current.baselineCorrection(inp, self.removeList, self.singleSlice.isChecked(), invert=self.invertButton.isChecked())
self.father.current.peakPickReset()
@@ -4312,15 +4304,15 @@ def applyFunc(self):
#############################################################
-class regionWindow(wc.ToolWindows):
+class regionWindow(wc.ToolWindow):
def __init__(self, parent, name):
self.NAME = name
super(regionWindow, self).__init__(parent)
self.startVal = [0] # dummy variables
self.endVal = [parent.current.len()] # dummy variables
- self.grid.addWidget(wc.QLabel("Start point:"), 0, 0)
- self.grid.addWidget(wc.QLabel("End point:"), 0, 1)
+ self.grid.addWidget(wc.QLabel("Start index:"), 0, 0)
+ self.grid.addWidget(wc.QLabel("End index:"), 0, 1)
self.startEntry = []
self.endEntry = []
self.deleteButton = []
@@ -4397,7 +4389,7 @@ def picked(self, pos):
self.father.current.peakPick = True
def setVal(self, entry, isMin=False):
- inp = safeEval(entry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(entry.text(), length=self.father.current.len(), Type='FI')
error = False
if inp is not None:
inp = int(inp)
@@ -4580,17 +4572,17 @@ def apply(self, maximum, minimum, newSpec):
#############################################################
-class regionWindow2(wc.ToolWindows):
+class regionWindow2(wc.ToolWindow):
def __init__(self, parent, name, newSpecOption):
self.NAME = name
super(regionWindow2, self).__init__(parent)
self.startVal = 0
self.endVal = parent.current.len()
- self.grid.addWidget(wc.QLabel("Start point:"), 0, 0)
+ self.grid.addWidget(wc.QLabel("Start index:"), 0, 0)
self.startEntry = wc.QLineEdit(self.startVal, self.checkValues)
self.grid.addWidget(self.startEntry, 1, 0)
- self.grid.addWidget(wc.QLabel("End point:"), 2, 0)
+ self.grid.addWidget(wc.QLabel("End index:"), 2, 0)
self.endEntry = wc.QLineEdit(self.endVal, self.checkValues)
self.grid.addWidget(self.endEntry, 3, 0)
self.newSpec = QtWidgets.QCheckBox("Result in new workspace")
@@ -4606,7 +4598,7 @@ def preview(self, maximum, minimum):
def picked(self, pos, second=False):
if second:
dataLength = self.father.current.len()
- inp = safeEval(self.startEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.startEntry.text(), length=self.father.current.len(), Type='FI')
if inp is not None:
self.startVal = int(round(inp))
if self.startVal < 0:
@@ -4626,7 +4618,7 @@ def picked(self, pos, second=False):
def checkValues(self, *args):
dataLength = self.father.current.len()
- inp = safeEval(self.startEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.startEntry.text(), length=self.father.current.len(), Type='FI')
if inp is not None:
self.startVal = int(round(inp))
if self.startVal < 0:
@@ -4634,7 +4626,7 @@ def checkValues(self, *args):
elif self.startVal > dataLength:
self.startVal = dataLength
self.startEntry.setText(str(self.startVal))
- inp = safeEval(self.endEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.endEntry.text(), length=self.father.current.len(), Type='FI')
if inp is not None:
self.endVal = int(round(inp))
if self.endVal < 0:
@@ -4646,7 +4638,7 @@ def checkValues(self, *args):
def applyFunc(self):
dataLength = self.father.current.len()
- inp = safeEval(self.startEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.startEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException(self.NAME + ": value not valid")
self.startVal = int(round(inp))
@@ -4654,7 +4646,7 @@ def applyFunc(self):
self.startVal = 0
elif self.startVal > dataLength:
self.startVal = dataLength
- inp = safeEval(self.endEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.endEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException(self.NAME + ": value not valid")
self.endVal = int(round(inp))
@@ -4719,7 +4711,7 @@ def apply(self, maximum, minimum, newSpec):
#############################################################
-class FiddleWindow(wc.ToolWindows):
+class FiddleWindow(wc.ToolWindow):
NAME = "Reference deconvolution"
@@ -4727,10 +4719,10 @@ def __init__(self, parent):
super(FiddleWindow, self).__init__(parent)
self.startVal = 0
self.endVal = parent.current.len()
- self.grid.addWidget(wc.QLabel("Start point:"), 0, 0)
+ self.grid.addWidget(wc.QLabel("Start index:"), 0, 0)
self.startEntry = wc.QLineEdit(self.startVal, self.checkValues)
self.grid.addWidget(self.startEntry, 1, 0)
- self.grid.addWidget(wc.QLabel("End point:"), 2, 0)
+ self.grid.addWidget(wc.QLabel("End index:"), 2, 0)
self.endEntry = wc.QLineEdit(self.endVal, self.checkValues)
self.grid.addWidget(self.endEntry, 3, 0)
self.grid.addWidget(wc.QLabel("Linebroadening [Hz]:"), 4, 0)
@@ -4742,7 +4734,7 @@ def __init__(self, parent):
def picked(self, pos, second=False):
if second:
dataLength = self.father.current.len()
- inp = safeEval(self.startEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.startEntry.text(), length=self.father.current.len(), Type='FI')
if inp is not None:
self.startVal = int(round(inp))
if self.startVal < 0:
@@ -4761,7 +4753,7 @@ def picked(self, pos, second=False):
def checkValues(self, *args):
dataLength = self.father.current.len()
- inp = safeEval(self.startEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.startEntry.text(), length=self.father.current.len(), Type='FI')
if inp is not None:
self.startVal = int(round(inp))
if self.startVal < 0:
@@ -4769,7 +4761,7 @@ def checkValues(self, *args):
elif self.startVal > dataLength:
self.startVal = dataLength
self.startEntry.setText(str(self.startVal))
- inp = safeEval(self.endEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.endEntry.text(), length=self.father.current.len(), Type='FI')
if inp is not None:
self.endVal = int(round(inp))
if self.endVal < 0:
@@ -4777,13 +4769,13 @@ def checkValues(self, *args):
elif self.endVal > dataLength:
self.endVal = dataLength
self.endEntry.setText(str(self.endVal))
- inp = safeEval(self.lbEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.lbEntry.text(), length=self.father.current.len(), Type='FI')
if inp is not None:
self.lbEntry.setText(str(inp))
def applyFunc(self):
dataLength = self.father.current.len()
- inp = safeEval(self.startEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.startEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("Reference deconv: start entry not valid")
self.startVal = int(round(inp))
@@ -4791,7 +4783,7 @@ def applyFunc(self):
self.startVal = 0
elif self.startVal > dataLength:
self.startVal = dataLength
- inp = safeEval(self.endEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.endEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("Reference deconv: end entry not valid")
self.endVal = int(round(inp))
@@ -4799,7 +4791,7 @@ def applyFunc(self):
self.endVal = 0
elif self.endVal > dataLength:
self.endVal = dataLength
- lb = safeEval(self.lbEntry.text(), length=self.father.current.len(), type='FI')
+ lb = safeEval(self.lbEntry.text(), length=self.father.current.len(), Type='FI')
if lb is None:
raise SsnakeException("Reference deconv: Linebroadening entry not valid")
self.father.current.fiddle(self.startVal, self.endVal, lb)
@@ -4807,7 +4799,7 @@ def applyFunc(self):
##############################################################
-class DeleteWindow(wc.ToolWindows):
+class DeleteWindow(wc.ToolWindow):
NAME = "Delete"
@@ -4845,7 +4837,7 @@ def applyFunc(self):
##############################################################
-class SplitWindow(wc.ToolWindows):
+class SplitWindow(wc.ToolWindow):
NAME = "Split"
@@ -4856,13 +4848,13 @@ def __init__(self, parent):
self.grid.addWidget(self.splitEntry, 1, 0)
def preview(self, *args):
- val = safeEval(self.splitEntry.text(), length=self.father.current.len(), type='FI')
+ val = safeEval(self.splitEntry.text(), length=self.father.current.len(), Type='FI')
if val is None:
raise SsnakeException("Split: input not valid")
self.splitEntry.setText(str(int(round(val))))
def applyFunc(self):
- val = safeEval(self.splitEntry.text(), length=self.father.current.len(), type='FI')
+ val = safeEval(self.splitEntry.text(), length=self.father.current.len(), Type='FI')
if val is None:
raise SsnakeException("Split: input not valid")
val = int(val)
@@ -4873,7 +4865,7 @@ def applyFunc(self):
##############################################################
-class ConcatenateWindow(wc.ToolWindows):
+class ConcatenateWindow(wc.ToolWindow):
NAME = "Concatenate"
@@ -4890,7 +4882,7 @@ def applyFunc(self):
##############################################################
-class InsertWindow(wc.ToolWindows):
+class InsertWindow(wc.ToolWindow):
NAME = "Insert"
@@ -4905,7 +4897,7 @@ def __init__(self, parent):
self.grid.addWidget(self.wsEntry, 3, 0)
def preview(self, *args):
- pos = safeEval(self.posEntry.text(), length=self.father.current.len(), type='FI')
+ pos = safeEval(self.posEntry.text(), length=self.father.current.len(), Type='FI')
if pos is None:
return
pos = int(round(pos))
@@ -4916,7 +4908,7 @@ def preview(self, *args):
self.posEntry.setText(str(pos))
def applyFunc(self):
- pos = safeEval(self.posEntry.text(), length=self.father.current.len(), type='FI')
+ pos = safeEval(self.posEntry.text(), length=self.father.current.len(), Type='FI')
if pos is None:
raise SsnakeException("Not a valid value")
pos = int(round(pos))
@@ -4930,7 +4922,7 @@ def applyFunc(self):
##############################################################
-class CombineWindow(wc.ToolWindows):
+class CombineWindow(wc.ToolWindow):
SINGLESLICE = True
RESIZABLE = True
@@ -4938,38 +4930,38 @@ class CombineWindow(wc.ToolWindows):
def __init__(self, parent, combType):
super(CombineWindow, self).__init__(parent)
self.combType = combType # 0 = add, 1 = subtract, 2 = multiply, 3 = divide
- if self.combType is 0:
+ if self.combType == 0:
self.WindowTitle = "Add"
self.grid.addWidget(wc.QLabel("Workspace to add:"), 0, 0)
- elif self.combType is 1:
+ elif self.combType == 1:
self.WindowTitle = "Subtract"
self.grid.addWidget(wc.QLabel("Workspace to subtract:"), 0, 0)
- elif self.combType is 2:
+ elif self.combType == 2:
self.WindowTitle = "Multiply"
self.grid.addWidget(wc.QLabel("Workspace to multiply:"), 0, 0)
- elif self.combType is 3:
+ elif self.combType == 3:
self.WindowTitle = "Divide"
self.grid.addWidget(wc.QLabel("Workspace to divide:"), 0, 0)
- self.setWindowTitle(self.WindowTitle)
+ self.setWindowTitle(self.WindowTitle)
self.wsEntry = QtWidgets.QComboBox()
self.wsEntry.addItems(self.father.father.workspaceNames)
self.grid.addWidget(self.wsEntry, 1, 0)
def applyFunc(self):
ws = self.wsEntry.currentIndex()
- if self.combType is 0:
+ if self.combType == 0:
returnValue = self.father.current.add(self.father.father.workspaces[ws].masterData.getData(), self.singleSlice.isChecked())
- elif self.combType is 1:
+ elif self.combType == 1:
returnValue = self.father.current.subtract(self.father.father.workspaces[ws].masterData.getData(), self.singleSlice.isChecked())
- elif self.combType is 2:
+ elif self.combType == 2:
returnValue = self.father.current.multiply(self.father.father.workspaces[ws].masterData.getData(), self.singleSlice.isChecked())
- elif self.combType is 3:
+ elif self.combType == 3:
returnValue = self.father.current.divide(self.father.father.workspaces[ws].masterData.getData(), self.singleSlice.isChecked())
##############################################################
-class SNWindow(wc.ToolWindows):
+class SNWindow(wc.ToolWindow):
NAME = "Signal to noise"
CANCELNAME = "&Close"
@@ -4978,16 +4970,16 @@ class SNWindow(wc.ToolWindows):
def __init__(self, parent):
super(SNWindow, self).__init__(parent)
- self.grid.addWidget(wc.QLabel("Start point noise:"), 0, 0)
+ self.grid.addWidget(wc.QLabel("Start index noise:"), 0, 0)
self.minNoiseEntry = wc.QLineEdit('0', self.checkValues)
self.grid.addWidget(self.minNoiseEntry, 1, 0)
- self.grid.addWidget(wc.QLabel("End point noise:"), 2, 0)
+ self.grid.addWidget(wc.QLabel("End index noise:"), 2, 0)
self.maxNoiseEntry = wc.QLineEdit(parent.current.len(), self.checkValues)
self.grid.addWidget(self.maxNoiseEntry, 3, 0)
- self.grid.addWidget(wc.QLabel("Start point signal:"), 4, 0)
+ self.grid.addWidget(wc.QLabel("Start index signal:"), 4, 0)
self.minEntry = wc.QLineEdit('0', self.checkValues)
self.grid.addWidget(self.minEntry, 5, 0)
- self.grid.addWidget(wc.QLabel("End point signal:"), 6, 0)
+ self.grid.addWidget(wc.QLabel("End index signal:"), 6, 0)
self.maxEntry = wc.QLineEdit(parent.current.len(), self.checkValues)
self.grid.addWidget(self.maxEntry, 7, 0)
self.grid.addWidget(wc.QLabel("S/N:"), 8, 0)
@@ -5017,7 +5009,7 @@ def picked(self, pos, num=0):
def checkValues(self, *args):
dataLength = self.father.current.len()
- inp = safeEval(self.minNoiseEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.minNoiseEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
return
minimum = int(round(inp))
@@ -5026,7 +5018,7 @@ def checkValues(self, *args):
elif minimum > dataLength:
minimum = dataLength
self.minNoiseEntry.setText(str(minimum))
- inp = safeEval(self.maxNoiseEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.maxNoiseEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
return
maximum = int(round(inp))
@@ -5035,7 +5027,7 @@ def checkValues(self, *args):
elif maximum > dataLength:
maximum = dataLength
self.maxNoiseEntry.setText(str(maximum))
- inp = safeEval(self.minEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.minEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
return
minimum = int(round(inp))
@@ -5044,7 +5036,7 @@ def checkValues(self, *args):
elif minimum > dataLength:
minimum = dataLength
self.minEntry.setText(str(minimum))
- inp = safeEval(self.maxEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.maxEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
return
maximum = int(round(inp))
@@ -5057,7 +5049,7 @@ def checkValues(self, *args):
def applyFunc(self):
dataLength = self.father.current.len()
- inp = safeEval(self.minNoiseEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.minNoiseEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("S/N: invalid range")
minimumNoise = int(round(inp))
@@ -5066,7 +5058,7 @@ def applyFunc(self):
elif minimumNoise > dataLength:
minimumNoise = dataLength
self.minNoiseEntry.setText(str(minimumNoise))
- inp = safeEval(self.maxNoiseEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.maxNoiseEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("S/N: invalid range")
maximumNoise = int(round(inp))
@@ -5075,7 +5067,7 @@ def applyFunc(self):
elif maximumNoise > dataLength:
maximumNoise = dataLength
self.maxNoiseEntry.setText(str(maximumNoise))
- inp = safeEval(self.minEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.minEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("S/N: invalid range")
minimum = int(round(inp))
@@ -5084,7 +5076,7 @@ def applyFunc(self):
elif minimum > dataLength:
minimum = dataLength
self.minEntry.setText(str(minimum))
- inp = safeEval(self.maxEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.maxEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("S/N: invalid range")
maximum = int(round(inp))
@@ -5098,7 +5090,7 @@ def applyFunc(self):
##############################################################
-class FWHMWindow(wc.ToolWindows):
+class FWHMWindow(wc.ToolWindow):
NAME = "FWHM"
CANCELNAME = "&Close"
@@ -5107,10 +5099,10 @@ class FWHMWindow(wc.ToolWindows):
def __init__(self, parent):
super(FWHMWindow, self).__init__(parent)
- self.grid.addWidget(wc.QLabel("Start point:"), 0, 0)
+ self.grid.addWidget(wc.QLabel("Start index:"), 0, 0)
self.minEntry = wc.QLineEdit('0', self.checkValues)
self.grid.addWidget(self.minEntry, 1, 0)
- self.grid.addWidget(wc.QLabel("End point:"), 2, 0)
+ self.grid.addWidget(wc.QLabel("End index:"), 2, 0)
self.maxEntry = wc.QLineEdit(parent.current.len(), self.checkValues)
self.grid.addWidget(self.maxEntry, 3, 0)
self.grid.addWidget(wc.QLabel("Units:"), 4, 0)
@@ -5148,7 +5140,7 @@ def picked(self, pos, num=0):
def checkValues(self, *args):
dataLength = self.father.current.len()
- inp = safeEval(self.minEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.minEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
return
minimum = int(round(inp))
@@ -5157,40 +5149,7 @@ def checkValues(self, *args):
elif minimum > dataLength:
minimum = dataLength
self.minEntry.setText(str(minimum))
- inp = safeEval(self.maxEntry.text(), length=self.father.current.len(), type='FI')
- if inp is None:
- return
- maximum = int(round(inp))
- if maximum < 0:
- maximum = 0
- elif maximum > dataLength:
- maximum = dataLength
- self.maxEntry.setText(str(maximum))
- self.applyFunc()
-
- def picked(self, pos, num=0):
- if num == 0:
- self.minEntry.setText(str(pos[0]))
- self.father.current.peakPickFunc = lambda pos, self=self: self.picked(pos, 1)
- self.father.current.peakPick = True
- elif num == 1:
- self.maxEntry.setText(str(pos[0]))
- self.father.current.peakPickFunc = lambda pos, self=self: self.picked(pos, 0)
- self.father.current.peakPick = True
- self.applyFunc()
-
- def checkValues(self, *args):
- dataLength = self.father.current.len()
- inp = safeEval(self.minEntry.text(), length=self.father.current.len(), type='FI')
- if inp is None:
- return
- minimum = int(round(inp))
- if minimum < 0:
- minimum = 0
- elif minimum > dataLength:
- minimum = dataLength
- self.minEntry.setText(str(minimum))
- inp = safeEval(self.maxEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.maxEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
return
maximum = int(round(inp))
@@ -5203,7 +5162,7 @@ def checkValues(self, *args):
def applyFunc(self):
dataLength = self.father.current.len()
- inp = safeEval(self.minEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.minEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("FWHM: invalid range")
minimum = int(round(inp))
@@ -5212,7 +5171,7 @@ def applyFunc(self):
elif minimum > dataLength:
minimum = dataLength
self.minEntry.setText(str(minimum))
- inp = safeEval(self.maxEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.maxEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("FWHM: invalid range")
maximum = int(round(inp))
@@ -5227,7 +5186,7 @@ def applyFunc(self):
##############################################################
-class COMWindow(wc.ToolWindows): # Centre of Mass Window
+class COMWindow(wc.ToolWindow): # Centre of Mass Window
NAME = "Centre of Mass"
CANCELNAME = "&Close"
@@ -5236,11 +5195,10 @@ class COMWindow(wc.ToolWindows): # Centre of Mass Window
def __init__(self, parent):
super(COMWindow, self).__init__(parent)
- self.pickDim = 1
+ self.pickDim = 1
if isinstance(self.father.current, views.CurrentContour):
- self.pickDim = 2
-
- self.grid.addWidget(wc.QLabel("X axis:"), 0, 0,1,2)
+ self.pickDim = 2
+ self.grid.addWidget(wc.QLabel("X axis:"), 0, 0, 1, 2)
self.grid.addWidget(wc.QLabel("Start:"), 1, 0)
self.grid.addWidget(wc.QLabel("End:"), 2, 0)
if self.pickDim == 2:
@@ -5251,12 +5209,12 @@ def __init__(self, parent):
unitSelectY = 3
else:
unitListY = ['s', 'ms', u'μs']
- self.grid.addWidget(wc.QLabel("Y axis:"), 3, 0,1,2)
+ self.grid.addWidget(wc.QLabel("Y axis:"), 3, 0, 1, 2)
self.grid.addWidget(wc.QLabel("Start:"), 4, 0)
self.grid.addWidget(wc.QLabel("End:"), 5, 0)
- self.minEntryY = wc.QLineEdit("0",lambda: self.applyFunc(False))
+ self.minEntryY = wc.QLineEdit("0", lambda: self.applyFunc(False))
self.grid.addWidget(self.minEntryY, 4, 1)
- self.maxEntryY = wc.QLineEdit(parent.current.len(-2),lambda: self.applyFunc(False))
+ self.maxEntryY = wc.QLineEdit(parent.current.len(-2), lambda: self.applyFunc(False))
self.grid.addWidget(self.maxEntryY, 5, 1)
self.grid.addWidget(wc.QLabel("Y Unit:"), 11, 0)
self.unitDropY = QtWidgets.QComboBox()
@@ -5267,20 +5225,18 @@ def __init__(self, parent):
self.comEntryY = wc.QLineEdit("0.0")
self.grid.addWidget(wc.QLabel(u"Y COM:"), 12, 0)
self.grid.addWidget(self.comEntryY, 12, 1)
-
if self.father.current.spec() == 1:
unitList = ['Hz', 'kHz', 'MHz', 'ppm']
if self.father.current.getppm():
unitSelect = 3
else:
unitList = ['s', 'ms', u'μs']
-
- self.minEntry = wc.QLineEdit("0",lambda: self.applyFunc(False))
+ self.minEntry = wc.QLineEdit("0", lambda: self.applyFunc(False))
self.grid.addWidget(self.minEntry, 1, 1)
- self.maxEntry = wc.QLineEdit(parent.current.len(),lambda: self.applyFunc(False))
+ self.maxEntry = wc.QLineEdit(parent.current.len(), lambda: self.applyFunc(False))
self.grid.addWidget(self.maxEntry, 2, 1)
unitSelect = self.father.current.getAxType()
- self.grid.addWidget(wc.QLabel(u"Centre of Mass:"), 8, 0,1,2)
+ self.grid.addWidget(wc.QLabel(u"Centre of Mass:"), 8, 0, 1, 2)
self.grid.addWidget(wc.QLabel("X Unit:"), 9, 0)
self.unitDrop = QtWidgets.QComboBox()
self.unitDrop.addItems(unitList)
@@ -5308,9 +5264,9 @@ def picked(self, pos, num=0):
self.father.current.peakPick = self.pickDim
self.applyFunc()
- def applyFunc(self,calc=True):
+ def applyFunc(self, calc=True):
dataLength = self.father.current.len()
- inp = safeEval(self.minEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.minEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("Centre of Mass: invalid range")
minimum = int(round(inp))
@@ -5319,7 +5275,7 @@ def applyFunc(self,calc=True):
elif minimum > dataLength:
minimum = dataLength
self.minEntry.setText(str(minimum))
- inp = safeEval(self.maxEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.maxEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("Centre of Mass: invalid range")
maximum = int(round(inp))
@@ -5331,7 +5287,7 @@ def applyFunc(self,calc=True):
#For contour
if self.pickDim == 2:
dataLengthY = self.father.current.len(-2)
- inp = safeEval(self.minEntryY.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.minEntryY.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("Centre of Mass: invalid range")
minimumY = int(round(inp))
@@ -5340,7 +5296,7 @@ def applyFunc(self,calc=True):
elif minimumY > dataLengthY:
minimumY = dataLengthY
self.minEntryY.setText(str(minimumY))
- inp = safeEval(self.maxEntryY.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.maxEntryY.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("Centre of Mass: invalid range")
maximumY = int(round(inp))
@@ -5352,9 +5308,9 @@ def applyFunc(self,calc=True):
if calc:
if self.pickDim == 1:
- self.comEntry.setText(str(self.father.current.COM([minimum], [maximum],[self.unitDrop.currentIndex()])[0]))
+ self.comEntry.setText(str(self.father.current.COM([minimum], [maximum], [self.unitDrop.currentIndex()])[0]))
elif self.pickDim == 2:
- com = self.father.current.COM([minimum, minimumY], [maximum,maximumY],[self.unitDrop.currentIndex(),self.unitDropY.currentIndex()])
+ com = self.father.current.COM([minimum, minimumY], [maximum, maximumY], [self.unitDrop.currentIndex(), self.unitDropY.currentIndex()])
self.comEntry.setText(str(com[0]))
self.comEntryY.setText(str(com[1]))
@@ -5362,7 +5318,7 @@ def applyFunc(self,calc=True):
##########################################################################################
-class IntegralsWindow(wc.ToolWindows):
+class IntegralsWindow(wc.ToolWindow):
NAME = "Integrals"
CANCELNAME = "&Close"
OKNAME = "C&alc"
@@ -5370,16 +5326,16 @@ class IntegralsWindow(wc.ToolWindows):
def __init__(self, parent):
super(IntegralsWindow, self).__init__(parent)
- self.pickDim = 1
+ self.pickDim = 1
if isinstance(self.father.current, views.CurrentContour):
- self.pickDim = 2
- self.grid.addWidget(wc.QLabel("Start point X:"), 0, 0)
- self.grid.addWidget(wc.QLabel("End point X:"), 0, 1)
+ self.pickDim = 2
+ self.grid.addWidget(wc.QLabel("Start index X:"), 0, 0)
+ self.grid.addWidget(wc.QLabel("End index X:"), 0, 1)
if self.pickDim == 2:
- self.grid.addWidget(wc.QLabel("Start point Y:"), 0, 2)
- self.grid.addWidget(wc.QLabel("End point Y:"), 0, 3)
+ self.grid.addWidget(wc.QLabel("Start index Y:"), 0, 2)
+ self.grid.addWidget(wc.QLabel("End index Y:"), 0, 3)
self.grid.addWidget(wc.QLabel("Integral:"), 0, 4)
- self.scaling = 1
+ self.scaling = 1
self.num = 0
self.pickType = 0
self.minEntries = []
@@ -5406,14 +5362,14 @@ def picked(self, pos):
self.xValues.append(None)
self.yValues.append(None)
self.intEntries[-1].setMinimumWidth(120)
- self.grid.addWidget(self.minEntries[-1],self.num + 1, 0)
- self.grid.addWidget(self.maxEntries[-1],self.num + 1, 1)
- self.grid.addWidget(self.intEntries[-1],self.num + 1, 4)
+ self.grid.addWidget(self.minEntries[-1], self.num+1, 0)
+ self.grid.addWidget(self.maxEntries[-1], self.num+1, 1)
+ self.grid.addWidget(self.intEntries[-1], self.num+1, 4)
if self.pickDim == 2:
self.minEntriesY.append(wc.QLineEdit(posY, self.applyFunc))
self.maxEntriesY.append(wc.QLineEdit('', self.applyFunc))
- self.grid.addWidget(self.minEntriesY[-1],self.num + 1, 2)
- self.grid.addWidget(self.maxEntriesY[-1],self.num + 1, 3)
+ self.grid.addWidget(self.minEntriesY[-1], self.num+1, 2)
+ self.grid.addWidget(self.maxEntriesY[-1], self.num+1, 3)
self.pickType = 1
elif self.pickType == 1:
self.maxEntries[-1].setText(pos)
@@ -5435,10 +5391,10 @@ def preview(self):
xMax = [int(x.text()) for x in self.maxEntries]
yMin = [int(x.text()) for x in self.minEntriesY]
yMax = [int(x.text()) for x in self.maxEntriesY]
- self.father.current.integralsPreview(xMin,xMax,yMin,yMax)
+ self.father.current.integralsPreview(xMin, xMax, yMin, yMax)
- def setScaling(self,num):
- inp = safeEval(self.intEntries[num].text(), length=self.father.current.len(), type='FI')
+ def setScaling(self, num):
+ inp = safeEval(self.intEntries[num].text(), length=self.father.current.len(), Type='FI')
int = self.intValues[num]
if inp is None:
return
@@ -5448,25 +5404,24 @@ def setScaling(self,num):
def applyFunc(self):
dataLength = [self.father.current.shape()[-1] - 1]
- Parts = [[self.minEntries],[self.maxEntries]]
+ Parts = [[self.minEntries], [self.maxEntries]]
if self.pickDim == 2:
dataLength.append(self.father.current.shape()[-2] - 1)
Parts[0].append(self.minEntriesY)
Parts[1].append(self.maxEntriesY)
-
for num in range(len(self.minEntries)):
- results = [[],[]] #The min/max results
+ results = [[], []] #The min/max results
ok = []
- for place in range(len(Parts)):
+ for place, _ in enumerate(Parts):
for i, part in enumerate(Parts[place]):
- inp = safeEval(part[num].text(), length=dataLength, type='FI')
+ inp = safeEval(part[num].text(), length=dataLength, Type='FI')
if inp is None:
part[num].setText('')
ok.append(False)
else:
ok.append(True)
tmp = int(round(inp))
- tmp = min(max(tmp,0),dataLength[i]) #makes sure that 0 < value < Length
+ tmp = min(max(tmp, 0), dataLength[i]) #makes sure that 0 < value < Length
results[place].append(tmp)
part[num].setText(str(tmp))
if all(ok):
@@ -5479,7 +5434,7 @@ def applyFunc(self):
##########################################################################################
-class ReorderWindow(wc.ToolWindows):
+class ReorderWindow(wc.ToolWindow):
NAME = "Reorder"
@@ -5504,7 +5459,7 @@ def getPosFromFile(self):
filename = filename[0]
if filename: # if not cancelled
self.father.father.lastLocation = os.path.dirname(filename) # Save used path
- if len(filename) == 0:
+ if not filename:
return
self.valEntry.setText(repr(np.loadtxt(filename, dtype=int)))
@@ -5513,7 +5468,7 @@ def applyFunc(self):
if newLength == '':
newLength = None
else:
- newLength = safeEval(self.lengthEntry.text(), length=self.father.current.len(), type='FI')
+ newLength = safeEval(self.lengthEntry.text(), length=self.father.current.len(), Type='FI')
if newLength is None:
raise SsnakeException("Reorder: `Length' input is not valid")
val = safeEval(self.valEntry.text(), length=int(self.father.current.len()))
@@ -5529,7 +5484,7 @@ def applyFunc(self):
##########################################################################################
-class RegridWindow(wc.ToolWindows):
+class RegridWindow(wc.ToolWindow):
NAME = "Regrid"
@@ -5583,13 +5538,13 @@ def __init__(self, parent):
self.closeEvent()
def applyFunc(self):
- maxVal = safeEval(self.maxValue.text(), length=self.father.current.len(), type='FI')
+ maxVal = safeEval(self.maxValue.text(), length=self.father.current.len(), Type='FI')
if maxVal is None:
raise SsnakeException("Regrid: 'Max' input not valid")
- minVal = safeEval(self.minValue.text(), length=self.father.current.len(), type='FI')
+ minVal = safeEval(self.minValue.text(), length=self.father.current.len(), Type='FI')
if minVal is None:
raise SsnakeException("Regrid: 'Min' input not valid")
- numPoints = safeEval(self.points.text(), length=self.father.current.len(), type='FI')
+ numPoints = safeEval(self.points.text(), length=self.father.current.len(), Type='FI')
if numPoints is None or numPoints == 1:
raise SsnakeException("Regrid: '# of points' input not valid")
numPoints = int(numPoints)
@@ -5608,7 +5563,7 @@ def applyFunc(self):
##########################################################################################
-class FFMWindow(wc.ToolWindows):
+class FFMWindow(wc.ToolWindow):
NAME = "FFM"
@@ -5635,7 +5590,7 @@ def getPosFromFile(self):
filename = filename[0]
if filename: # if not cancelled
self.father.father.lastLocation = os.path.dirname(filename) # Save used path
- if len(filename) == 0:
+ if not filename:
return
self.valEntry.setText(repr(np.loadtxt(filename, dtype=int)))
@@ -5651,7 +5606,7 @@ def applyFunc(self):
##########################################################################################
-class CLEANWindow(wc.ToolWindows):
+class CLEANWindow(wc.ToolWindow):
NAME = "CLEAN"
@@ -5686,7 +5641,7 @@ def getPosFromFile(self):
filename = filename[0]
if filename: # if not cancelled
self.father.father.lastLocation = os.path.dirname(filename) # Save used path
- if len(filename) == 0:
+ if not filename:
return
self.valEntry.setText(repr(np.loadtxt(filename, dtype=int)))
@@ -5695,14 +5650,14 @@ def applyFunc(self):
if not isinstance(val, (list, np.ndarray)):
raise SsnakeException("CLEAN: 'Positions' is not a list or array")
val = np.array(val, dtype=int)
- gamma = safeEval(self.gammaEntry.text(), length=self.father.current.len(), type='FI')
+ gamma = safeEval(self.gammaEntry.text(), length=self.father.current.len(), Type='FI')
if gamma is None:
raise SsnakeException("CLEAN: 'Gamma' input is not valid")
- threshold = safeEval(self.thresholdEntry.text(), length=self.father.current.len(), type='FI')
+ threshold = safeEval(self.thresholdEntry.text(), length=self.father.current.len(), Type='FI')
if threshold is None:
raise SsnakeException("CLEAN: 'Threshold' input is not valid")
threshold = threshold
- maxIter = safeEval(self.maxIterEntry.text(), length=self.father.current.len(), type='FI')
+ maxIter = safeEval(self.maxIterEntry.text(), length=self.father.current.len(), Type='FI')
if maxIter is None:
raise SsnakeException("CLEAN: 'Max. iter.' is not valid")
maxIter = int(maxIter)
@@ -5713,7 +5668,7 @@ def applyFunc(self):
################################################################
-class ISTWindow(wc.ToolWindows):
+class ISTWindow(wc.ToolWindow):
NAME = "IST"
@@ -5748,7 +5703,7 @@ def getPosFromFile(self):
filename = filename[0]
if filename: # if not cancelled
self.father.father.lastLocation = os.path.dirname(filename) # Save used path
- if len(filename) == 0:
+ if not filename:
return
self.valEntry.setText(repr(np.loadtxt(filename, dtype=int)))
@@ -5757,14 +5712,14 @@ def applyFunc(self):
if not isinstance(val, (list, np.ndarray)):
raise SsnakeException("IST: 'Positions' input is not a list or array")
val = np.array(val, dtype=int)
- tracelimit = safeEval(self.tracelimitEntry.text(), length=self.father.current.len(), type='FI')
+ tracelimit = safeEval(self.tracelimitEntry.text(), length=self.father.current.len(), Type='FI')
if tracelimit is None:
raise SsnakeException("IST: 'Residual' input is not valid")
tracelimit /= 100
- threshold = safeEval(self.thresholdEntry.text(), length=self.father.current.len(), type='FI')
+ threshold = safeEval(self.thresholdEntry.text(), length=self.father.current.len(), Type='FI')
if threshold is None:
raise SsnakeException("IST: 'Threshold' input is not valid")
- maxIter = safeEval(self.maxIterEntry.text(), length=self.father.current.len(), type='FI')
+ maxIter = safeEval(self.maxIterEntry.text(), length=self.father.current.len(), Type='FI')
if maxIter is None:
raise SsnakeException("IST: 'Max. iter.' input is not valid")
maxIter = int(maxIter)
@@ -5775,7 +5730,7 @@ def applyFunc(self):
################################################################
-class ShearingWindow(wc.ToolWindows):
+class ShearingWindow(wc.ToolWindow):
NAME = "Shearing"
@@ -5809,12 +5764,12 @@ def dropdownChanged(self):
self.shearEntry.setText("%.9f" % self.shearList[index])
def shearPreview(self, *args):
- shear = safeEval(self.shearEntry.text(), length=self.father.current.len(), type='FI')
+ shear = safeEval(self.shearEntry.text(), length=self.father.current.len(), Type='FI')
if shear is not None:
self.shearEntry.setText(str(float(shear)))
def applyFunc(self):
- shear = safeEval(self.shearEntry.text(), length=self.father.current.len(), type='FI')
+ shear = safeEval(self.shearEntry.text(), length=self.father.current.len(), Type='FI')
if shear is None:
raise SsnakeException("Shearing: 'constant' not a valid value")
axis = self.dirEntry.currentIndex()
@@ -5826,7 +5781,7 @@ def applyFunc(self):
##########################################################################################
-class MultiplyWindow(wc.ToolWindows):
+class MultiplyWindow(wc.ToolWindow):
NAME = "Multiply"
SINGLESLICE = True
@@ -5851,22 +5806,22 @@ def applyFunc(self):
##########################################################################################
-class NormalizeWindow(wc.ToolWindows):
+class NormalizeWindow(wc.ToolWindow):
NAME = "Normalize"
SINGLESLICE = True
def __init__(self, parent):
super(NormalizeWindow, self).__init__(parent)
- self.grid.addWidget(wc.QLabel("Start point:"), 0, 0)
+ self.grid.addWidget(wc.QLabel("Start index:"), 0, 0)
self.minEntry = wc.QLineEdit("0", self.checkValues)
self.grid.addWidget(self.minEntry, 1, 0)
- self.grid.addWidget(wc.QLabel("End point:"), 2, 0)
+ self.grid.addWidget(wc.QLabel("End index:"), 2, 0)
self.maxEntry = wc.QLineEdit(parent.current.len(), self.checkValues)
self.grid.addWidget(self.maxEntry, 3, 0)
self.grid.addWidget(wc.QLabel("Type:"), 4, 0)
self.typeDrop = QtWidgets.QComboBox()
- self.typeDrop.addItems(['Integral','Maximum','Minimum'])
+ self.typeDrop.addItems(['Integral', 'Maximum', 'Minimum'])
self.typeDrop.setCurrentIndex(0)
self.typeDrop.currentIndexChanged.connect(self.checkValues)
self.grid.addWidget(self.typeDrop, 5, 0)
@@ -5889,7 +5844,7 @@ def picked(self, pos, num=0):
def checkValues(self, *args):
dataLength = self.father.current.len()
- inp = safeEval(self.minEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.minEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
return
minimum = int(round(inp))
@@ -5898,7 +5853,7 @@ def checkValues(self, *args):
elif minimum > dataLength:
minimum = dataLength
self.minEntry.setText(str(minimum))
- inp = safeEval(self.maxEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.maxEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
return
maximum = int(round(inp))
@@ -5911,7 +5866,7 @@ def checkValues(self, *args):
def applyFunc(self):
dataLength = self.father.current.len()
- inp = safeEval(self.minEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.minEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("Normalize: invalid range")
minimum = int(round(inp))
@@ -5920,7 +5875,7 @@ def applyFunc(self):
elif minimum > dataLength:
minimum = dataLength
self.minEntry.setText(str(minimum))
- inp = safeEval(self.maxEntry.text(), length=self.father.current.len(), type='FI')
+ inp = safeEval(self.maxEntry.text(), length=self.father.current.len(), Type='FI')
if inp is None:
raise SsnakeException("Normalize: invalid range")
maximum = int(round(inp))
@@ -5930,7 +5885,7 @@ def applyFunc(self):
maximum = dataLength
self.maxEntry.setText(str(maximum))
try:
- scale = safeEval(self.valEntry.text(), length=self.father.current.len(), type='FI')
+ scale = safeEval(self.valEntry.text(), length=self.father.current.len(), Type='FI')
except Exception:
raise SsnakeException("Normalize: invalid multiplier")
type = self.typeDrop.currentIndex()
@@ -5944,7 +5899,7 @@ def applyFunc(self):
##########################################################################################
-class XaxWindow(wc.ToolWindows):
+class XaxWindow(wc.ToolWindow):
RESIZABLE = True
NAME = "User defined x-axis"
@@ -5952,7 +5907,7 @@ class XaxWindow(wc.ToolWindows):
def __init__(self, parent):
super(XaxWindow, self).__init__(parent)
self.axisSize = self.father.current.len()
- self.grid.addWidget(wc.QLabel("Input x-axis values:"), 0, 0, 1, 2)
+ self.grid.addWidget(wc.QLabel("Input x-axis values:"), 0, 0, 1, 2)
self.typeDropdown = QtWidgets.QComboBox()
self.typeDropdown.addItems(['Expression', 'Linear', 'Logarithmic'])
self.typeDropdown.activated.connect(self.typeChanged)
@@ -6042,14 +5997,16 @@ def getValues(self):
env['euro'] = lambda fVal, num=self.axisSize: func.euro(fVal, num)
try:
val = np.array(eval(self.exprEntry.text(), env),dtype=float) # find a better solution, also add catch for exceptions
- except Exception:
+ except SyntaxError:
try:
val = np.fromstring(self.exprEntry.text(), sep=' ')
val2 = np.fromstring(self.exprEntry.text(), sep=',')
if len(val2) > len(val):
val = val2
- except Exception:
- val = None
+ except Exception as e:
+ raise SsnakeException(str(e))
+ except Exception as e:
+ raise SsnakeException(str(e))
if not isinstance(val, (list, np.ndarray)):
raise SsnakeException("X-axis: Input is not a list or array")
if len(val) != self.father.current.len():
@@ -6057,16 +6014,16 @@ def getValues(self):
if not all(isinstance(x, (int, float)) for x in val):
raise SsnakeException("X-axis: Array is not all of int or float type")
elif self.typeDropdown.currentIndex() == 1:
- start = safeEval(self.linStartEntry.text(), type='FI')
- stop = safeEval(self.linStopEntry.text(), type='FI')
+ start = safeEval(self.linStartEntry.text(), Type='FI')
+ stop = safeEval(self.linStopEntry.text(), Type='FI')
if start is None:
raise SsnakeException("X-axis: linear start value is not valid")
if stop is None:
raise SsnakeException("X-axis: linear stop value is not valid")
val = np.linspace(start, stop, self.axisSize)
elif self.typeDropdown.currentIndex() == 2:
- start = safeEval(self.logStartEntry.text(), type='FI')
- stop = safeEval(self.logStopEntry.text(), type='FI')
+ start = safeEval(self.logStartEntry.text(), Type='FI')
+ stop = safeEval(self.logStopEntry.text(), Type='FI')
if start is None or start <= 0.0:
raise SsnakeException("X-axis: logarithmic start value is not valid")
if stop is None or stop <= 0.0:
@@ -6093,7 +6050,7 @@ def applyFunc(self):
##########################################################################################
-class RefWindow(wc.ToolWindows):
+class RefWindow(wc.ToolWindow):
NAME = "Reference"
@@ -6131,8 +6088,8 @@ def __init__(self, parent):
self.father.current.peakPick = True
def preview(self, *args):
- freq = safeEval(self.freqEntry.text(), length=self.father.current.len(), type='FI')
- ref = safeEval(self.refEntry.text(), length=self.father.current.len(), type='FI')
+ freq = safeEval(self.freqEntry.text(), length=self.father.current.len(), Type='FI')
+ ref = safeEval(self.refEntry.text(), length=self.father.current.len(), Type='FI')
if freq is None or ref is None:
return
self.freqEntry.setText("%.7f" % (freq))
@@ -6143,8 +6100,8 @@ def fillSecondaryRef(self):
def applyAndClose(self):
self.father.current.peakPickReset()
- freq = safeEval(self.freqEntry.text(), length=self.father.current.len(), type='FI')
- ref = safeEval(self.refEntry.text(), length=self.father.current.len(), type='FI')
+ freq = safeEval(self.freqEntry.text(), length=self.father.current.len(), Type='FI')
+ ref = safeEval(self.refEntry.text(), length=self.father.current.len(), Type='FI')
if freq is None or ref is None:
raise SsnakeException("Not a valid value")
freq = freq * 1e6
@@ -6170,7 +6127,7 @@ def picked(self, pos):
##########################################################################################
-class HistoryWindow(wc.ToolWindows):
+class HistoryWindow(wc.ToolWindow):
NAME = "Processing history"
RESIZABLE = True
@@ -6191,7 +6148,7 @@ def __init__(self, parent):
class OrigListWidget(QtWidgets.QListWidget):
- def __init__(self, parent=None,dest=None):
+ def __init__(self, parent=None, dest=None):
super(OrigListWidget, self).__init__(parent)
self.setDragDropMode(QtWidgets.QAbstractItemView.DragDrop)
self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
@@ -6206,7 +6163,7 @@ def dropEvent(self, event):
for item in self.dest.selectedItems():
self.dest.takeItem(self.dest.row(item))
- def mouseDoubleClickEvent(self,event):
+ def mouseDoubleClickEvent(self, event):
for item in self.selectedItems():
QtWidgets.QListWidgetItem(item.text(), self.dest)
@@ -6238,13 +6195,13 @@ def deleteSelected(self):
for item in self.selectedItems():
self.takeItem(self.row(item))
- def mouseDoubleClickEvent(self,event):
+ def mouseDoubleClickEvent(self, event):
self.deleteSelected()
##########################################################################################
-class CombineWorkspaceWindow(wc.ToolWindows):
+class CombineWorkspaceWindow(wc.ToolWindow):
NAME = "Combine workspaces"
RESIZABLE = True
@@ -6254,7 +6211,7 @@ def __init__(self, parent):
self.grid.addWidget(wc.QLabel("Workspaces:"), 0, 0)
self.grid.addWidget(wc.QLabel("Combined spectrum:"), 0, 1)
self.listB = DestListWidget(self)
- self.listA = OrigListWidget(self,self.listB)
+ self.listA = OrigListWidget(self, self.listB)
for i in self.father.workspaceNames:
QtWidgets.QListWidgetItem(i, self.listA).setToolTip(i)
self.grid.addWidget(self.listA, 1, 0)
@@ -6266,7 +6223,7 @@ def applyFunc(self, *args):
items = []
for index in range(self.listB.count()):
items.append(self.listB.item(index).text())
- if len(items) == 0:
+ if not items:
raise SsnakeException("Please select at least one workspace to combine")
self.father.combineWorkspace(items)
@@ -6278,7 +6235,7 @@ def closeEvent(self, *args):
##########################################################################################
-class CombineLoadWindow(wc.ToolWindows):
+class CombineLoadWindow(wc.ToolWindow):
NAME = "Open & Combine"
BROWSE = True
@@ -6310,7 +6267,7 @@ def browse(self):
for filePath in fileList:
if filePath: # if not cancelled
self.father.lastLocation = os.path.dirname(filePath) # Save used path
- if len(filePath) == 0:
+ if not filePath:
return
self.specList.addItem(filePath)
@@ -6318,7 +6275,7 @@ def applyFunc(self, *args):
items = []
for index in range(self.specList.count()):
items.append(self.specList.item(index).text())
- if len(items) == 0:
+ if not items:
raise SsnakeException("Please select at least one workspace to combine")
self.father.loadAndCombine(items)
@@ -6349,7 +6306,7 @@ def __init__(self, parent):
self.listB = DestListWidget(self)
for i in self.father.monitorMacros:
QtWidgets.QListWidgetItem(i, self.listB).setToolTip(i)
- self.listA = OrigListWidget(self,self.listB)
+ self.listA = OrigListWidget(self, self.listB)
for i in self.father.father.macros.keys():
QtWidgets.QListWidgetItem(i, self.listA).setToolTip(i)
grid.addWidget(self.listA, 1, 0)
@@ -6369,9 +6326,9 @@ def __init__(self, parent):
unwatchButton.clicked.connect(self.stopAndClose)
box = QtWidgets.QDialogButtonBox()
- box.addButton(cancelButton,QtWidgets.QDialogButtonBox.RejectRole)
- box.addButton(watchButton,QtWidgets.QDialogButtonBox.ActionRole)
- box.addButton(unwatchButton,QtWidgets.QDialogButtonBox.ActionRole)
+ box.addButton(cancelButton, QtWidgets.QDialogButtonBox.RejectRole)
+ box.addButton(watchButton, QtWidgets.QDialogButtonBox.ActionRole)
+ box.addButton(unwatchButton, QtWidgets.QDialogButtonBox.ActionRole)
layout.addWidget(box, 3, 0)
layout.setColumnStretch(4, 1)
self.show()
@@ -6399,7 +6356,7 @@ def closeEvent(self, *args):
##############################################################################
-class PlotSettingsWindow(wc.ToolWindows):
+class PlotSettingsWindow(wc.ToolWindow):
NAME = "Preferences"
@@ -6477,7 +6434,7 @@ def preview(self, *args):
self.father.current.setLw(self.lwSpinBox.value())
tmpXTicks = self.father.current.viewSettings["minXTicks"]
tmpYTicks = self.father.current.viewSettings["minYTicks"]
- self.father.current.setTickNum(self.xTicksSpinBox.value(),self.yTicksSpinBox.value())
+ self.father.current.setTickNum(self.xTicksSpinBox.value(), self.yTicksSpinBox.value())
tmpColor = self.father.current.viewSettings["color"]
self.father.current.setColor(self.color)
tmpColorRange = self.father.current.getColorRange()
@@ -6492,7 +6449,7 @@ def preview(self, *args):
self.father.current.setContourColors([self.posColor, self.negColor])
self.father.current.showFid()
self.father.current.setLw(tmpLw)
- self.father.current.setTickNum(tmpXTicks,tmpYTicks)
+ self.father.current.setTickNum(tmpXTicks, tmpYTicks)
self.father.current.setColor(tmpColor)
self.father.current.setColorRange(tmpColorRange)
self.father.current.setColorMap(tmpColorMap)
@@ -6521,7 +6478,7 @@ def setNegColor(self, *args):
def applyFunc(self, *args):
self.father.current.setColor(self.color)
self.father.current.setLw(self.lwSpinBox.value())
- self.father.current.setTickNum(self.xTicksSpinBox.value(),self.yTicksSpinBox.value())
+ self.father.current.setTickNum(self.xTicksSpinBox.value(), self.yTicksSpinBox.value())
self.father.current.setGrids([self.xgridCheck.isChecked(), self.ygridCheck.isChecked()])
self.father.current.setColorRange(self.crEntry.currentIndex())
self.father.current.setColorMap(self.cmEntry.currentIndex())
@@ -6531,7 +6488,7 @@ def applyFunc(self, *args):
##############################################################################
-class errorWindow(wc.ToolWindows):
+class errorWindow(wc.ToolWindow):
NAME = "Error Messages"
RESIZABLE = True
@@ -6619,6 +6576,9 @@ def __init__(self, parent):
self.toolbarCheck = QtWidgets.QCheckBox("Show Shortcut Toolbar")
self.toolbarCheck.setChecked(self.father.defaultToolBar)
grid1.addWidget(self.toolbarCheck, 5, 0, 1, 2)
+ self.tooltipCheck = QtWidgets.QCheckBox("Show Tooltips")
+ self.tooltipCheck.setChecked(self.father.defaultTooltips)
+ grid1.addWidget(self.tooltipCheck, 7, 0, 1, 2)
editToolbarButton = QtWidgets.QPushButton("Edit Toolbar")
editToolbarButton.clicked.connect(lambda: ToolbarWindow(self))
grid1.addWidget(editToolbarButton, 6, 0, 1, 2)
@@ -6626,7 +6586,7 @@ def __init__(self, parent):
self.startupgroupbox = QtWidgets.QGroupBox("Startup Directory")
self.startupgroupbox.setCheckable(True)
self.startupgroupbox.setChecked(self.father.defaultStartupBool)
- grid1.addWidget(self.startupgroupbox, 7, 0, 1, 2)
+ grid1.addWidget(self.startupgroupbox, 8, 0, 1, 2)
startupgrid = QtWidgets.QGridLayout()
self.startupgroupbox.setLayout(startupgrid)
self.startupDirEntry = QtWidgets.QLineEdit(self)
@@ -6726,9 +6686,9 @@ def __init__(self, parent):
resetButton = QtWidgets.QPushButton("&Reset")
resetButton.clicked.connect(self.reset)
box = QtWidgets.QDialogButtonBox()
- box.addButton(cancelButton,QtWidgets.QDialogButtonBox.RejectRole)
- box.addButton(okButton,QtWidgets.QDialogButtonBox.ActionRole)
- box.addButton(resetButton,QtWidgets.QDialogButtonBox.ActionRole)
+ box.addButton(cancelButton, QtWidgets.QDialogButtonBox.RejectRole)
+ box.addButton(okButton, QtWidgets.QDialogButtonBox.ActionRole)
+ box.addButton(resetButton, QtWidgets.QDialogButtonBox.ActionRole)
layout.addWidget(box, 1,0)
layout.setColumnStretch(3, 1)
self.show()
@@ -6737,7 +6697,7 @@ def browseStartup(self, *args):
newDir = QtWidgets.QFileDialog.getExistingDirectory(self, 'Select Directory', self.father.lastLocation, QtWidgets.QFileDialog.ShowDirsOnly)
if newDir:
self.startupDirEntry.setText(newDir)
-
+
def setColor(self, *args):
tmp = QtWidgets.QColorDialog.getColor(QtGui.QColor(self.color))
if tmp.isValid():
@@ -6761,6 +6721,7 @@ def applyAndClose(self, *args):
self.father.defaultMaximized = self.maximizedCheck.isChecked()
self.father.defaultAskName = self.askNameCheck.isChecked()
self.father.defaultToolBar = self.toolbarCheck.isChecked()
+ self.father.defaultTooltips = self.tooltipCheck.isChecked()
self.father.defaultToolbarActionList = self.currentToolbar
self.father.defaultStartupBool = self.startupgroupbox.isChecked()
self.father.defaultStartupDir = self.startupDirEntry.text()
@@ -6794,7 +6755,7 @@ def closeEvent(self, *args):
##############################################################################
-class ToolbarWindow(wc.ToolWindows):
+class ToolbarWindow(wc.ToolWindow):
NAME = "Change Toolbar"
RESIZABLE = True
@@ -6807,7 +6768,7 @@ def __init__(self, parent):
self.listB = DestListWidget(self)
for i in self.father.father.defaultToolbarActionList:
QtWidgets.QListWidgetItem(i, self.listB).setToolTip(i)
- self.listA = OrigListWidget(self,self.listB)
+ self.listA = OrigListWidget(self, self.listB)
for i in self.father.father.allActionsList:
QtWidgets.QListWidgetItem(i[0], self.listA).setToolTip(i[0])
self.grid.addWidget(self.listA, 1, 0)
@@ -6827,7 +6788,7 @@ def closeEvent(self, *args):
##############################################################################
-class aboutWindow(wc.ToolWindows):
+class aboutWindow(wc.ToolWindow):
NAME = "About ssNake"
RESIZABLE = True
@@ -6852,7 +6813,7 @@ def __init__(self, parent):
pythonVersion = pythonVersion[:pythonVersion.index(' ')]
from scipy import __version__ as scipyVersion
self.text.setText('ssNake ' + VERSION + '
' +
- 'Copyright (©) 2016–2019 Bas van Meerten & Wouter Franssen<\p>' + '
Email: ssnake@science.ru.nl
' +
+ 'Copyright (©) 2016–2019 Bas van Meerten & Wouter Franssen
' + 'Email: ssnake@science.ru.nl
' +
'Publication: https://doi.org/10.1016/j.jmr.2019.02.006
' +
'Library versions:
Python ' + pythonVersion + '
numpy ' + np.__version__ +
'
SciPy ' + scipyVersion +
@@ -6875,7 +6836,7 @@ def closeEvent(self, *args):
##############################################################################
-class shiftConversionWindow(wc.ToolWindows):
+class shiftConversionWindow(wc.ToolWindow):
NAME = "Chemical Shift Conversions"
MENUDISABLE = False
@@ -6989,33 +6950,33 @@ def __init__(self, parent):
def shiftCalc(self, Type):
if Type == 0: # If from standard
try:
- delta11 = float(safeEval(self.D11.text(), type='FI'))
- delta22 = float(safeEval(self.D22.text(), type='FI'))
- delta33 = float(safeEval(self.D33.text(), type='FI'))
+ delta11 = float(safeEval(self.D11.text(), Type='FI'))
+ delta22 = float(safeEval(self.D22.text(), Type='FI'))
+ delta33 = float(safeEval(self.D33.text(), Type='FI'))
Values = [delta11, delta22, delta33]
except Exception:
raise SsnakeException("Shift Conversion: Invalid input in Standard Convention")
if Type == 1: # If from xyz
try:
- delta11 = float(safeEval(self.dxx.text(), type='FI')) # Treat xyz as 123, as it reorders them anyway
- delta22 = float(safeEval(self.dyy.text(), type='FI'))
- delta33 = float(safeEval(self.dzz.text(), type='FI'))
+ delta11 = float(safeEval(self.dxx.text(), Type='FI')) # Treat xyz as 123, as it reorders them anyway
+ delta22 = float(safeEval(self.dyy.text(), Type='FI'))
+ delta33 = float(safeEval(self.dzz.text(), Type='FI'))
Values = [delta11, delta22, delta33]
except Exception:
raise SsnakeException("Shift Conversion: Invalid input in xyz Convention")
if Type == 2: # From haeberlen
try:
- eta = float(safeEval(self.eta.text(), type='FI'))
- delta = float(safeEval(self.daniso.text(), type='FI'))
- iso = float(safeEval(self.diso.text(), type='FI'))
+ eta = float(safeEval(self.eta.text(), Type='FI'))
+ delta = float(safeEval(self.daniso.text(), Type='FI'))
+ iso = float(safeEval(self.diso.text(), Type='FI'))
Values = [iso, delta, eta]
except Exception:
raise SsnakeException("Shift Conversion: Invalid input in Haeberlen Convention")
if Type == 3: # From Hertzfeld-Berger
try:
- iso = float(safeEval(self.hbdiso.text(), type='FI'))
- span = float(safeEval(self.hbdaniso.text(), type='FI'))
- skew = float(safeEval(self.hbskew.text(), type='FI'))
+ iso = float(safeEval(self.hbdiso.text(), Type='FI'))
+ span = float(safeEval(self.hbdaniso.text(), Type='FI'))
+ skew = float(safeEval(self.hbskew.text(), Type='FI'))
Values = [iso, span, skew]
except Exception:
raise SsnakeException("Shift Conversion: Invalid input in Hertzfeld-Berger Convention")
@@ -7063,7 +7024,7 @@ def closeEvent(self):
##############################################################################
-class quadConversionWindow(wc.ToolWindows):
+class quadConversionWindow(wc.ToolWindow):
Ioptions = ['1', '3/2', '2', '5/2', '3', '7/2', '4', '9/2', '5', '6', '7']
Ivalues = [1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0]
@@ -7077,16 +7038,14 @@ def __init__(self, parent):
self.comFrame = QtWidgets.QGridLayout()
nucLabel = wc.QLabel("Nucleus:")
self.comFrame.addWidget(nucLabel, 0, 0)
-
- qindex = [x for (x,val) in enumerate(ISOTOPES['q']) if val is not None and ISOTOPES['spin'][x] != 0.5]
- self.names = ['User'] + [val for (x,val) in enumerate(ISOTOPES['formatName']) if x in qindex]
- self.I = [0.0] + [val for (x,val) in enumerate(ISOTOPES['spin']) if x in qindex]
- self.Qvalues = [0.0] + [val for (x,val) in enumerate(ISOTOPES['q']) if x in qindex]
+ qindex = [x for (x, val) in enumerate(ISOTOPES['q']) if val is not None and ISOTOPES['spin'][x] != 0.5]
+ self.names = ['User'] + [val for (x, val) in enumerate(ISOTOPES['formatName']) if x in qindex]
+ self.I = [0.0] + [val for (x, val) in enumerate(ISOTOPES['spin']) if x in qindex]
+ self.Qvalues = [0.0] + [val for (x, val) in enumerate(ISOTOPES['q']) if x in qindex]
self.nucDrop = QtWidgets.QComboBox()
self.nucDrop.addItems(self.names)
self.nucDrop.currentIndexChanged.connect(self.setNuc)
self.comFrame.addWidget(self.nucDrop, 1, 0)
-
Itext = wc.QLabel("I:")
self.comFrame.addWidget(Itext, 0, 1)
self.IEntry = QtWidgets.QComboBox()
@@ -7161,13 +7120,13 @@ def __init__(self, parent):
self.okButton.clicked.disconnect()
self.okButton.clicked.connect(self.valueReset)
- def setNuc(self,index):
+ def setNuc(self, index):
I = self.I[index]
if int(I * 2) > 0:
self.IEntry.setCurrentIndex(int(I * 2 - 2))
self.Moment.setText(str(self.Qvalues[index]))
- def userChange(self,index = None):
+ def userChange(self, index=None):
self.nucDrop.setCurrentIndex(0)
def quadCalc(self, Type):
@@ -7175,42 +7134,42 @@ def quadCalc(self, Type):
if Type == 0: # Cq as input
# Czz is equal to Cq, via same definition (scale) Cxx and Cyy can be found
try:
- Cq = float(safeEval(self.Cq.text(), type='FI'))
- Eta = float(safeEval(self.Eta.text(), type='FI'))
- Values = [ Cq, Eta]
+ Cq = float(safeEval(self.Cq.text(), Type='FI'))
+ Eta = float(safeEval(self.Eta.text(), Type='FI'))
+ Values = [Cq, Eta]
except Exception:
raise SsnakeException("Quad Conversion: Invalid input in Cq definition")
if Type == 1:
try:
- Wq = float(safeEval(self.Wq.text(), type='FI'))
- Eta = float(safeEval(self.Eta.text(), type='FI'))
- Values = [ Wq, Eta]
+ Wq = float(safeEval(self.Wq.text(), Type='FI'))
+ Eta = float(safeEval(self.Eta.text(), Type='FI'))
+ Values = [Wq, Eta]
except Exception:
raise SsnakeException("Quad Conversion: Invalid input in Wq definition")
if Type == 2:
try:
- Vxx = float(safeEval(self.Vxx.text(), type='FI'))
- Vyy = float(safeEval(self.Vyy.text(), type='FI'))
- Vzz = float(safeEval(self.Vzz.text(), type='FI'))
- Values = [ Vxx, Vyy, Vzz]
+ Vxx = float(safeEval(self.Vxx.text(), Type='FI'))
+ Vyy = float(safeEval(self.Vyy.text(), Type='FI'))
+ Vzz = float(safeEval(self.Vzz.text(), Type='FI'))
+ Values = [Vxx, Vyy, Vzz]
except Exception:
raise SsnakeException("Quad Conversion: Invalid input in field gradients")
try:
- Q = float(safeEval(self.Moment.text(), type='FI')) * 1e-30 # get moment and convert from fm^2
+ Q = float(safeEval(self.Moment.text(), Type='FI')) * 1e-30 # get moment and convert from fm^2
except Exception:
- if Type == 0 or Type == 1:
+ if Type in (0, 1):
Q = None
else:
raise SsnakeException("Quad Conversion: Invalid input in quadrupole moment Q")
#Do conversion
- Result = func.quadConversion(Values,I, Type, Q)
- if Result[0][1] == None:
+ Result = func.quadConversion(Values, I, Type, Q)
+ if Result[0][1] is None:
self.Eta.setText('ND')
else:
self.Eta.setText('%#.4g' % Result[0][1])
self.Cq.setText('%#.4g' % Result[0][0])
self.Wq.setText('%#.4g' % Result[1][0])
- if Result[2][0] == None:
+ if Result[2][0] is None:
self.Moment.setText('ND')
self.Vxx.setText('ND')
self.Vyy.setText('ND')
@@ -7234,7 +7193,7 @@ def closeEvent(self):
##############################################################################
-class dipolarDistanceWindow(wc.ToolWindows):
+class dipolarDistanceWindow(wc.ToolWindow):
NAME = "Dipolar Distance Calculation"
RESIZABLE = True
@@ -7247,10 +7206,9 @@ def __init__(self, parent):
gamma1label = wc.QLabel(u'γ1 [107 rad/s/T]:')
self.comFrame.addWidget(gamma1label, 0, 0)
- gammaindex = [x for (x,val) in enumerate(ISOTOPES['gamma']) if val is not None]
- self.gammaValues = [0.0] + [val for (x,val) in enumerate(ISOTOPES['gamma']) if x in gammaindex]
- self.names = ['User'] + [val for (x,val) in enumerate(ISOTOPES['formatName']) if x in gammaindex]
-
+ gammaindex = [x for (x, val) in enumerate(ISOTOPES['gamma']) if val is not None]
+ self.gammaValues = [0.0] + [val for (x, val) in enumerate(ISOTOPES['gamma']) if x in gammaindex]
+ self.names = ['User'] + [val for (x, val) in enumerate(ISOTOPES['formatName']) if x in gammaindex]
self.gamma1Drop = QtWidgets.QComboBox()
self.gamma1Drop.addItems(self.names)
self.gamma1Drop.currentIndexChanged.connect(self.setGamma1)
@@ -7259,7 +7217,6 @@ def __init__(self, parent):
self.gamma2Drop.addItems(self.names)
self.gamma2Drop.currentIndexChanged.connect(self.setGamma2)
self.comFrame.addWidget(self.gamma2Drop, 1, 1)
-
self.gamma1 = wc.QLineEdit("0.0")
self.gamma1.setMinimumWidth(100)
self.gamma1.textEdited.connect(self.gamma1Changed)
@@ -7272,7 +7229,6 @@ def __init__(self, parent):
self.comFrame.addWidget(self.gamma2, 2, 1)
self.comGroup.setLayout(self.comFrame)
self.grid.addWidget(self.comGroup, 1, 0, 1, 3)
-
self.distanceGroup = QtWidgets.QGroupBox("Distance:")
self.distanceFrame = QtWidgets.QGridLayout()
distancelabel = wc.QLabel(u'r [â„«]')
@@ -7313,32 +7269,30 @@ def gamma1Changed(self):
def gamma2Changed(self):
self.gamma2Drop.setCurrentIndex(0)
- def setGamma1(self,index):
- if index !=0:
+ def setGamma1(self, index):
+ if index != 0:
self.gamma1.setText(str(self.gammaValues[index]))
- def setGamma2(self,index):
- if index !=0:
+ def setGamma2(self, index):
+ if index != 0:
self.gamma2.setText(str(self.gammaValues[index]))
def Calc(self, Type):
try:
- gamma1 = float(safeEval(self.gamma1.text(), type='FI')) * 1e7
- gamma2 = float(safeEval(self.gamma2.text(), type='FI')) * 1e7
+ gamma1 = float(safeEval(self.gamma1.text(), Type='FI')) * 1e7
+ gamma2 = float(safeEval(self.gamma2.text(), Type='FI')) * 1e7
except Exception:
raise SsnakeException("Dipolar Distance: Invalid input in gamma values")
-
if Type == 0: # Distance as input
try:
- r = abs(float(safeEval(self.distance.text(), type='FI')))
+ r = abs(float(safeEval(self.distance.text(), Type='FI')))
except Exception:
raise SsnakeException("Dipolar Distance: Invalid input in r")
if Type == 1:
try:
- D = abs(float(safeEval(self.dipolar.text(), type='FI')))
+ D = abs(float(safeEval(self.dipolar.text(), Type='FI')))
except Exception:
raise SsnakeException("Dipolar Distance: Invalid input in D")
-
hbar = 1.054573e-34
if Type == 0:
if r == 0.0:
@@ -7352,7 +7306,6 @@ def Calc(self, Type):
else:
r = 1 / abs(D * 1000 /gamma1 / gamma2 / hbar / 1e-7 * (2 * np.pi))**(1.0/3)
r *= 1e10
-
self.dipolar.setText('%#.5g' % D)
self.distance.setText('%#.5g' % r)
@@ -7381,7 +7334,6 @@ class tempCalWindow(QtWidgets.QWidget):
lambda Delta: 466.5 - 102.00 * Delta,
lambda Temp: (Temp - 466.5) / -102.0,
'absShift',None,None,'Ammann et al., JMR, 46, 319 (1982)']
-
PBNO3 = [143, 423,
lambda Delta, Delta0, T0: (Delta0 - Delta) / 0.753 + T0 ,
lambda T, Delta0, T0: (T0 - T) * 0.753 + Delta0 ,
@@ -7390,12 +7342,9 @@ class tempCalWindow(QtWidgets.QWidget):
lambda Delta, Delta0, T0: (Delta0 - Delta) / 0.0250 + T0 ,
lambda T, Delta0, T0: (T0 - T) * 0.0250 + Delta0 ,
'relShift','0','293','Thurber et al., JMR, 196, 84 (2009)']
-
-
DEFINITIONS = [METHANOL, ETH_GLYCOL, PBNO3 ,KBR]
TEXTLIST = ['1H: Methanol (178 K < T < 330 K)', '1H: Ethylene Glycol (273 K < T < 416 K)',
'207Pb: Lead Nitrate (143 K < T < 423 K)','79Br: KBr (170 K < T < 320 K)']
-
T1_KBr = [20,296,
lambda Relax: optimize.brentq(lambda T,T1: 0.0145 + 5330/T**2 + 1.42e7/T**4 + 2.48e9/T**6 - T1, 20, 296 ,args=(Relax,)),
lambda T: 0.0145 + 5330/T**2 + 1.42e7/T**4 + 2.48e9/T**6,
@@ -7404,10 +7353,8 @@ class tempCalWindow(QtWidgets.QWidget):
lambda Relax: optimize.brentq(lambda T,T1: -1.6e-3 + 1.52e3/T**2 + 0.387e6/T**4 + 0.121e9/T**6 - T1, 8, 104 ,args=(Relax,)),
lambda T: -1.6e-3 + 1.52e3/T**2 + 0.387e6/T**4 + 0.121e9/T**6,
'Sarkar et al., JMR, 212, 460 (2011)']
-
T1_DEFINITIONS = [T1_KBr, T1_CsI]
- T1_TEXTLIST = ['79Br: KBr (20 K < T < 296 K, 9.4 T)','127I: CsI (8 K < T < 104 K, 9.4 T)']
-
+ T1_TEXTLIST = ['79Br: KBr (20 K < T < 296 K, 9.4 T)', '127I: CsI (8 K < T < 104 K, 9.4 T)']
def __init__(self, parent):
super(tempCalWindow, self).__init__(parent)
@@ -7419,13 +7366,11 @@ def __init__(self, parent):
tabWidget.addTab(tab1, "Chemical Shift Based")
grid1 = QtWidgets.QGridLayout()
tab1.setLayout(grid1)
-
- #Shift based
+ # Shift based
self.typeDrop = QtWidgets.QComboBox()
self.typeDrop.addItems(self.TEXTLIST)
grid1.addWidget(self.typeDrop, 0, 0)
self.typeDrop.currentIndexChanged.connect(self.changeType)
-
self.RefGroup = QtWidgets.QGroupBox("Relative to:")
self.RefFrame = QtWidgets.QGridLayout()
self.Delta0Label = wc.QLabel(u'δ [ppm]')
@@ -7441,7 +7386,6 @@ def __init__(self, parent):
self.RefGroup.setLayout(self.RefFrame)
grid1.addWidget(self.RefGroup, 1, 0)
self.RefGroup.hide()
-
self.DeltaGroup = QtWidgets.QGroupBox("Shift to Temperature:")
self.DeltaFrame = QtWidgets.QGridLayout()
self.DeltaLabel = wc.QLabel(u'Δδ [ppm]')
@@ -7454,7 +7398,6 @@ def __init__(self, parent):
self.DeltaFrame.addWidget(self.Delta, 1, 1)
self.DeltaGroup.setLayout(self.DeltaFrame)
grid1.addWidget(self.DeltaGroup, 2, 0)
-
self.TempGroup = QtWidgets.QGroupBox("Temperature to Shift:")
self.TempFrame = QtWidgets.QGridLayout()
TempLabel = wc.QLabel(u'Temperature [K]')
@@ -7468,19 +7411,16 @@ def __init__(self, parent):
self.TempGroup.setLayout(self.TempFrame)
grid1.addWidget(self.TempGroup, 3, 0)
self.refname = wc.QLabel(self.DEFINITIONS[0][7])
- grid1.addWidget(self.refname,4,0)
-
- #T1 based
+ grid1.addWidget(self.refname, 4, 0)
+ # T1 based
tab2 = QtWidgets.QWidget()
tabWidget.addTab(tab2, "T1 Based")
grid2 = QtWidgets.QGridLayout()
tab2.setLayout(grid2)
-
self.T1typeDrop = QtWidgets.QComboBox()
self.T1typeDrop.addItems(self.T1_TEXTLIST)
grid2.addWidget(self.T1typeDrop, 0, 0)
self.T1typeDrop.currentIndexChanged.connect(self.changeTypeT1)
-
self.T1Group = QtWidgets.QGroupBox("T1 to Temperature:")
self.T1Frame = QtWidgets.QGridLayout()
self.T1Label = wc.QLabel(u'T1 [s]')
@@ -7493,7 +7433,6 @@ def __init__(self, parent):
self.T1Frame.addWidget(self.T1, 1, 1)
self.T1Group.setLayout(self.T1Frame)
grid2.addWidget(self.T1Group, 2, 0)
-
self.TempT1Group = QtWidgets.QGroupBox("Temperature to T1:")
self.TempT1Frame = QtWidgets.QGridLayout()
TempT1Label = wc.QLabel(u'Temperature [K]')
@@ -7507,23 +7446,22 @@ def __init__(self, parent):
self.TempT1Group.setLayout(self.TempT1Frame)
grid2.addWidget(self.TempT1Group, 3, 0)
self.refnameT1 = wc.QLabel(self.T1_DEFINITIONS[0][4])
- grid2.addWidget(self.refnameT1,4,0)
-
+ grid2.addWidget(self.refnameT1, 4, 0)
layout = QtWidgets.QGridLayout(self)
layout.addWidget(tabWidget, 0, 0, 1, 4)
cancelButton = QtWidgets.QPushButton("&Close")
cancelButton.clicked.connect(self.closeEvent)
box = QtWidgets.QDialogButtonBox()
- box.addButton(cancelButton,QtWidgetsQ.DialogButtonBox.RejectRole)
- layout.addWidget(box, 1,0,1,4)
+ box.addButton(cancelButton, QtWidgets.QDialogButtonBox.RejectRole)
+ layout.addWidget(box, 1, 0, 1, 4)
layout.setColumnStretch(3, 1)
+# layout.setRowStretch(3, 1)
self.show()
self.setFixedSize(self.size())
- def changeType(self,index):
+ def changeType(self, index):
self.Temp.setText('')
self.Delta.setText('')
-
self.refname.setText(self.DEFINITIONS[index][7])
if self.DEFINITIONS[self.typeDrop.currentIndex()][4] == 'absShift':
self.DeltaLabel.setText(u'Δδ [ppm]')
@@ -7535,15 +7473,18 @@ def changeType(self,index):
self.RefGroup.show()
self.Delta0.setText(self.DEFINITIONS[self.typeDrop.currentIndex()][5])
self.T0.setText(self.DEFINITIONS[self.typeDrop.currentIndex()][6])
+ self.father.root.processEvents()
+ self.setFixedSize(self.sizeHint())
- def changeTypeT1(self,index):
+ def changeTypeT1(self, index):
self.refnameT1.setText(self.T1_DEFINITIONS[index][4])
-
+ self.father.root.processEvents()
+ self.setFixedSize(self.sizeHint())
def tempToT1(self):
Data = self.T1_DEFINITIONS[self.T1typeDrop.currentIndex()]
try:
- Temp = float(safeEval(self.TempT1.text(), type='FI'))
+ Temp = float(safeEval(self.TempT1.text(), Type='FI'))
except Exception:
self.T1.setText('?')
raise SsnakeException("Temperature Calibration: Invalid input in Temp value")
@@ -7551,17 +7492,15 @@ def tempToT1(self):
if Temp < Data[0] or Temp > Data[1]:
self.T1.setText('?')
raise SsnakeException("Temperature Calibration: Temperature outside calibration range")
- else:
- self.T1.setText('%#.6g' % T1)
+ self.T1.setText('%#.6g' % T1)
def t1ToTemp(self):
Data = self.T1_DEFINITIONS[self.T1typeDrop.currentIndex()]
try:
- T1 = float(safeEval(self.T1.text(), type='FI'))
+ T1 = float(safeEval(self.T1.text(), Type='FI'))
except Exception:
self.TempT1.setText('?')
raise SsnakeException("Temperature Calibration: Invalid input in Temp value")
-
try:
Temp = Data[2](T1)
except Exception:
@@ -7572,62 +7511,57 @@ def t1ToTemp(self):
def shiftToTemp(self):
Data = self.DEFINITIONS[self.typeDrop.currentIndex()]
try:
- Delta = float(safeEval(self.Delta.text(), type='FI'))
+ Delta = float(safeEval(self.Delta.text(), Type='FI'))
except Exception:
self.Temp.setText('?')
raise SsnakeException("Temperature Calibration: Invalid input in Delta value")
if Data[4] == 'relShift':
try:
- Delta0 = float(safeEval(self.Delta0.text(), type='FI'))
- T0 = float(safeEval(self.T0.text(), type='FI'))
+ Delta0 = float(safeEval(self.Delta0.text(), Type='FI'))
+ T0 = float(safeEval(self.T0.text(), Type='FI'))
except Exception:
self.Temp.setText('?')
raise SsnakeException("Temperature Calibration: Invalid input in References values")
- Temp = Data[2](Delta,Delta0,T0)
+ Temp = Data[2](Delta, Delta0, T0)
else:
Temp = Data[2](Delta)
-
if Temp < Data[0] or Temp > Data[1]:
self.Temp.setText('?')
raise SsnakeException("Temperature Calibration: Temperature outside calibration range")
- else:
- self.Temp.setText('%#.6g' % Temp)
+ self.Temp.setText('%#.6g' % Temp)
def tempToShift(self):
Data = self.DEFINITIONS[self.typeDrop.currentIndex()]
try:
- Temp = float(safeEval(self.Temp.text(), type='FI'))
+ Temp = float(safeEval(self.Temp.text(), Type='FI'))
except Exception:
self.Delta.setText('?')
raise SsnakeException("Temperature Calibration: Invalid input in Temp value")
if Data[4] == 'relShift':
try:
- Delta0 = float(safeEval(self.Delta0.text(), type='FI'))
- T0 = float(safeEval(self.T0.text(), type='FI'))
+ Delta0 = float(safeEval(self.Delta0.text(), Type='FI'))
+ T0 = float(safeEval(self.T0.text(), Type='FI'))
except Exception:
self.Delta.setText('?')
raise SsnakeException("Temperature Calibration: Invalid input in References values")
- Delta = Data[3](Temp,Delta0,T0)
+ Delta = Data[3](Temp, Delta0, T0)
else:
Delta = Data[3](Temp)
if Temp < Data[0] or Temp > Data[1]:
self.Delta.setText('?')
raise SsnakeException("Temperature Calibration: Temperature outside calibration range")
- else:
- self.Delta.setText('%#.6g' % Delta)
-
-
+ self.Delta.setText('%#.6g' % Delta)
def closeEvent(self, *args):
self.deleteLater()
##############################################################################
-class mqmasExtractWindow(wc.ToolWindows):
+class mqmasExtractWindow(wc.ToolWindow):
Ioptions = ['3/2','5/2', '7/2', '9/2']
Ivalues = [1.5, 2.5, 3.5, 4.5]
- z = [680.0/27.0,8500.0/81.0,6664.0/27.0,1360.0/3.0]
- BdevA = [1.0/68.0,3.0/850.0,5.0/3332.0,1.0/1224.0]
+ z = [680.0/27.0, 8500.0/81.0, 6664.0/27.0, 1360.0/3.0]
+ BdevA = [1.0/68.0, 3.0/850.0, 5.0/3332.0, 1.0/1224.0]
NAME = "MQMAS"
RESIZABLE = True
MENUDISABLE = False
@@ -7657,7 +7591,7 @@ def __init__(self, parent):
self.delta1.setMinimumWidth(200)
self.calcIsoPqButton = QtWidgets.QPushButton("Calc δiso/PQ", self)
self.calcIsoPqButton.clicked.connect(self.calcIsoPq)
- self.onetwoFrame.addWidget(self.calcIsoPqButton, 4, 0,1,2)
+ self.onetwoFrame.addWidget(self.calcIsoPqButton, 4, 0, 1, 2)
self.onetwoGroup.setLayout(self.onetwoFrame)
self.grid.addWidget(self.onetwoGroup, 2, 0, 4, 2)
self.isopqGroup = QtWidgets.QGroupBox("δiso/PQ:")
@@ -7670,7 +7604,7 @@ def __init__(self, parent):
self.isopqFrame.addWidget(self.pq, 7, 1)
self.calc12Button = QtWidgets.QPushButton("Calc δ1/δ2", self)
self.calc12Button.clicked.connect(self.calc12)
- self.isopqFrame.addWidget(self.calc12Button, 8, 0,1,2)
+ self.isopqFrame.addWidget(self.calc12Button, 8, 0, 1, 2)
self.isopqGroup.setLayout(self.isopqFrame)
self.grid.addWidget(self.isopqGroup, 6, 0, 4, 2)
self.cancelButton.setText("Close")
@@ -7681,16 +7615,16 @@ def __init__(self, parent):
self.okButton.clicked.connect(self.valueReset)
def calcIsoPq(self):
- nu0 = safeEval(self.nu0.text(), type='FI')
+ nu0 = safeEval(self.nu0.text(), Type='FI')
wrong = False
if nu0 is None:
self.father.dispMsg("MQMAS Extract: Invalid input in V0")
wrong = True
- delta1 = safeEval(self.delta1.text(), type='FI')
+ delta1 = safeEval(self.delta1.text(), Type='FI')
if delta1 is None and wrong is False:
self.father.dispMsg("MQMAS Extract: Invalid input in Delta1")
wrong = True
- delta2 = safeEval(self.delta2.text(), type='FI')
+ delta2 = safeEval(self.delta2.text(), Type='FI')
if delta2 is None and wrong is False:
self.father.dispMsg("MQMAS Extract: Invalid input in Delta2")
wrong = True
@@ -7709,16 +7643,16 @@ def calcIsoPq(self):
self.pq.setText(str(pq))
def calc12(self):
- nu0 = safeEval(self.nu0.text(), type='FI')
+ nu0 = safeEval(self.nu0.text(), Type='FI')
wrong = False
if nu0 is None or nu0 == 0.0:
self.father.dispMsg("MQMAS Extract: Invalid input in V0")
wrong = True
- iso = safeEval(self.deltaIso.text(), type='FI')
+ iso = safeEval(self.deltaIso.text(), Type='FI')
if iso is None and wrong is False:
self.father.dispMsg("MQMAS Extract: Invalid input in DeltaIso")
wrong = True
- pq = safeEval(self.pq.text(), type='FI')
+ pq = safeEval(self.pq.text(), Type='FI')
if pq is None and wrong is False:
self.father.dispMsg("MQMAS Extract: Invalid input in PQ")
wrong = True
@@ -7729,7 +7663,7 @@ def calc12(self):
BdevA = self.BdevA[self.IEntry.currentIndex()]
delta1 = iso + BdevA * pq**2/nu0**2 * 1e6
self.delta1.setText(str(delta1))
- delta2 = (27 * iso - 17 * delta1) / 10
+ delta2 = (27 * iso - 17 * delta1) / 10
self.delta2.setText(str(delta2))
def valueReset(self): # Resets all the boxes to 0
@@ -7772,9 +7706,9 @@ def checkVersions():
If the values are to low, an error message is returned.
"""
from scipy import __version__ as scipyVersion # Scipy is not fully imported, so only load version
- libs = [['numpy',np.__version__,NPVERSION],
- ['matplotlib',matplotlib.__version__,MPLVERSION],
- ['scipy',scipyVersion,SPVERSION]]
+ libs = [['numpy', np.__version__, NPVERSION],
+ ['matplotlib', matplotlib.__version__, MPLVERSION],
+ ['scipy', scipyVersion, SPVERSION]]
if sys.version_info.major == 3:
libs.append(['python', str(sys.version_info.major) + '.' + str(sys.version_info.minor), PY3VERSION])
elif sys.version_info.major == 2:
@@ -7796,12 +7730,30 @@ def popupVersionError(messages):
msg = ""
for elem in messages:
msg = msg + elem + '\n'
- reply = QtWidgets.QMessageBox.warning(QtWidgets.QWidget(),'Invalid software version', msg, QtWidgets.QMessageBox.Ignore, QtWidgets.QMessageBox.Abort)
+ reply = QtWidgets.QMessageBox.warning(QtWidgets.QWidget(), 'Invalid software version', msg, QtWidgets.QMessageBox.Ignore, QtWidgets.QMessageBox.Abort)
quit = False
if reply == QtWidgets.QMessageBox.Abort:
quit = True
return quit
+def openRefMan():
+ file = os.path.dirname(os.path.realpath(__file__)) + os.path.sep + '..' + os.path.sep + 'ReferenceManual.pdf'
+ if sys.platform.startswith('linux'):
+ os.system("xdg-open " + '"' + file + '"')
+ elif sys.platform.startswith('darwin'):
+ os.system("open " + '"' + file + '"')
+ elif sys.platform.startswith('win'):
+ os.startfile(file)
+
+def openTutorial():
+ path = os.path.dirname(os.path.realpath(__file__)) + os.path.sep + '..' + os.path.sep + '/Tutorial'
+ if sys.platform.startswith('linux'):
+ os.system("xdg-open " + '"' + path + '"')
+ elif sys.platform.startswith('darwin'):
+ os.system("open " + '"' + path + '"')
+ elif sys.platform.startswith('win'):
+ os.startfile(path)
+
if __name__ == '__main__':
error, messages = checkVersions()
quit = False
@@ -7820,10 +7772,9 @@ def exception_hook(exctype, value, traceback):
if not isinstance(value, Exception): # Do not catch keyboard interrupts
sys._excepthook(exctype, value, traceback)
elif isinstance(value, (sc.SpectrumException, hc.HComplexException, sim.SimException)):
- mainProgram.dispMsg(str(value))
+ mainProgram.dispMsg(str(value))
else:
mainProgram.dispError([exctype, value, traceback])
sys.excepthook = exception_hook
sys.exit(root.exec_())
-
diff --git a/src/updateWindow.py b/src/updateWindow.py
index bb746c58..7ed6b38c 100644
--- a/src/updateWindow.py
+++ b/src/updateWindow.py
@@ -28,11 +28,23 @@
else:
from urllib import urlopen, urlretrieve
import ssNake as sc
-from ssNake import QtGui, QtCore, QtWidgets
+from ssNake import QtCore, QtWidgets
+
class UpdateWindow(QtWidgets.QWidget):
+ """
+ The window for updating ssNake.
+ """
def __init__(self, parent):
+ """
+ Initializes the update window.
+
+ Parameters
+ ----------
+ parent : MainProgram
+ The mainprogram object of ssNake.
+ """
super(UpdateWindow, self).__init__(parent)
self.setWindowFlags(QtCore.Qt.Window | QtCore.Qt.Tool)
self.father = parent
@@ -45,7 +57,7 @@ def __init__(self, parent):
req.close()
self.nameList = [u'develop']
self.urlList = [u'https://api.github.com/repos/smeerten/ssnake/zipball/develop']
- for i in range(len(info)):
+ for i, _ in enumerate(info):
self.nameList.append(info[i]['name'])
self.urlList.append(info[i]['zipball_url'])
except Exception:
@@ -65,16 +77,22 @@ def __init__(self, parent):
okButton = QtWidgets.QPushButton("&Ok")
okButton.clicked.connect(self.applyAndClose)
box = QtWidgets.QDialogButtonBox()
- box.addButton(cancelButton,QtWidgets.QDialogButtonBox.RejectRole)
- box.addButton(okButton,QtWidgets.QDialogButtonBox.AcceptRole)
+ box.addButton(cancelButton, QtWidgets.QDialogButtonBox.RejectRole)
+ box.addButton(okButton, QtWidgets.QDialogButtonBox.AcceptRole)
layout.addWidget(box, 2, 0)
layout.setColumnStretch(1, 1)
self.show()
def closeEvent(self, *args):
+ """
+ Closes the update window.
+ """
self.deleteLater()
def applyAndClose(self, *args):
+ """
+ Asks the user to update and closes the window.
+ """
ssnake_location = os.path.dirname(os.path.dirname(__file__))
try:
os.mkdir(ssnake_location + os.path.sep + 'test')
diff --git a/src/views.py b/src/views.py
index 07179220..c335f534 100644
--- a/src/views.py
+++ b/src/views.py
@@ -17,8 +17,8 @@
# You should have received a copy of the GNU General Public License
# along with ssNake. If not, see .
-import numpy as np
import copy
+import numpy as np
from matplotlib.pyplot import get_cmap, colormaps
import matplotlib
import matplotlib.ticker as ticker
@@ -62,8 +62,8 @@ def __init__(self, root, fig, canvas, data, duplicateCurrent=None):
"ppm": np.array([self.root.father.defaultPPM] * self.NDIM_PLOT, dtype=bool), # display frequency as ppm
"color": self.root.father.defaultColor,
"linewidth": self.root.father.defaultLinewidth,
- "minXTicks": self.root.father.defaultMinXTicks,
- "minYTicks": self.root.father.defaultMinYTicks,
+ "minXTicks": self.root.father.defaultMinXTicks,
+ "minYTicks": self.root.father.defaultMinYTicks,
"grids": self.root.father.defaultGrids,
"colorRange": self.root.father.defaultColorRange,
"colorMap": self.root.father.defaultColorMap,
@@ -96,8 +96,7 @@ def __init__(self, root, fig, canvas, data, duplicateCurrent=None):
"stackBegin": None,
"stackEnd": None,
"stackStep": None,
- "spacing": 0,
- }
+ "spacing": 0}
self.upd() # get the first slice of data
if self.viewSettings['showTitle']:
self.fig.suptitle(self.data.name)
@@ -140,65 +139,280 @@ def __init__(self, root, fig, canvas, data, duplicateCurrent=None):
self.startUp(xReset, yReset)
def shape(self):
+ """
+ Returns the shape of the data
+
+ Returns
+ -------
+ tuple:
+ The shape along each dimension
+ """
return self.data1D.shape()
def len(self, dim=-1):
+ """
+ Returns the length of a specific dimension of the data. By default
+ the last dimension (-1) is selected.
+
+ Parameters
+ ----------
+ dim (optional = -1): int
+ The dimension of which the length should be returned.
+
+ Returns
+ -------
+ int:
+ The length
+ """
return self.shape()[dim]
-
+
def ndim(self):
+ """
+ Returns the number of dimensions of the data.
+
+ Returns
+ -------
+ int:
+ The number of dimension
+ """
return self.data1D.ndim()
def freq(self, dim=-1):
+ """
+ Returns the spectrum frequency of a specified dimension
+ (i.e. centre frequency) in hertz.
+ By default, the last dimension (-1) is selected.
+
+ Parameters
+ ----------
+ dim (optional = -1): int
+ The dimension of which the frequency should be returned.
+
+ Returns
+ -------
+ float:
+ The frequency
+ """
return self.data1D.freq[dim]
def ref(self, dim=-1):
+ """
+ Returns the reference frequency in Hz for a selected dimension.
+ By default, the last dimension (-1) is selected.
+ If no reference is defined for the dimension, the centre frequency
+ is retuned instead.
+
+ Parameters
+ ----------
+ dim (optional = -1): int
+ The dimension of which the reference frequency should be returned.
+
+ Returns
+ -------
+ float:
+ The reference frequency of the dimension
+ """
if self.data1D.ref[dim] is not None:
return self.data1D.ref[dim]
- else:
- return self.data1D.freq[dim]
+ return self.data1D.freq[dim]
def sw(self, dim=-1):
+ """
+ Returns the spectral width (sweep width) in Hz for a selected dimension.
+ By default, the last dimension (-1) is selected.
+
+ Parameters
+ ----------
+ dim (optional = -1): int
+ The dimension of which the sw should be returned.
+
+ Returns
+ -------
+ float:
+ The spectral width of the dimension
+ """
return self.data1D.sw[dim]
def spec(self, dim=-1):
+ """
+ Returns the state of a specified dimension (spectrum or FID).
+ By default, the last dimension (-1) is selected.
+
+ Parameters
+ ----------
+ dim (optional = -1): int
+ The dimension of which the spec/fid state should be returned.
+
+ Returns
+ -------
+ bool:
+ True for spectrum, False for FID.
+ """
return self.data1D.spec[dim]
def xax(self, dim=-1):
+ """
+ Returns the x-axis for the selected dimension.
+ By default, the last dimension (-1) is selected.
+
+ Parameters
+ ----------
+ dim (optional = -1): int
+ The dimension of which the x-axis state should be returned.
+
+ Returns
+ -------
+ ndarray:
+ 1D array with the x-axis.
+ """
return self.data1D.xaxArray[dim]
def wholeEcho(self, dim=-1):
+ """
+ Returns the whole Echo boolean for the selected dimension.
+ By default, the last dimension (-1) is selected.
+
+ Parameters
+ ----------
+ dim (optional = -1): int
+ The dimension of which the whole echo state should be returned.
+
+ Returns
+ -------
+ bool:
+ The whole echo state of the dimension.
+ """
return self.data1D.wholeEcho[dim]
-
+
def getCurrentAxMult(self, axis=-1):
+ """
+ Returns the axis multiplier (i.e. unit) for the selected dimension.
+ By default, the last dimension (-1) is selected.
+
+ Parameters
+ ----------
+ axis (optional = -1): int
+ The dimension of which the multiplier should be returned.
+
+ Returns
+ -------
+ float:
+ The multiplier for the dimension.
+ """
return self.getAxMult(self.spec(axis), self.getAxType(), self.getppm(), self.freq(axis), self.ref(axis))
def getAxType(self, num=-1):
+ """
+ Returns the axis type (i.e. unit) for the selected dimension.
+ By default, the last dimension (-1) is selected.
+
+ The type can be 0,1,2 or 3.
+ For a spectrum axis:
+ 0: Hz
+ 1: kHz
+ 2: MHz
+ 3: ppm
+
+ For an FID axis:
+ 0: s
+ 1: ms
+ 2: us
+
+ Parameters
+ ----------
+ num (optional = -1): int
+ The dimension of which the type should be returned.
+
+ Returns
+ -------
+ int:
+ The type index for the dimension.
+ """
return self.viewSettings["axType"][num]
def getppm(self, num=-1):
+ """
+ Get the ppm boolean of the selected dimension.
+ By default, the last dimension (-1) is selected.
+ Is always False for FID axes.
+
+ Parameters
+ ----------
+ num (optional = -1): int
+ The dimension of which the ppm boolean should be returned.
+
+ Returns
+ -------
+ bool:
+ True if the axis is in ppm, False if not.
+ """
if self.data1D.ref[num] == 0.0 or self.data1D.freq[num] == 0.0:
return False
- else:
- return self.viewSettings["ppm"][num]
+ return self.viewSettings["ppm"][num]
def getDataType(self, data):
+ """
+ Returns the input data in the current representation
+ (real, imag, both, abs).
+
+ Parameters
+ ----------
+ data: ndarray
+ The data that should be converted to the representation
+
+ Returns
+ -------
+ ndarray:
+ The changed data
+ """
+
typeList = [np.real, np.imag, np.array, np.abs]
return typeList[self.viewSettings["plotType"]](data)
-
+
def startUp(self, xReset=True, yReset=True):
+ """
+ Plot the data, with optional resets of the x an y axis limits.
+
+ Parameters
+ ----------
+ xReset (optional = True): bool
+ Whether to reset the x-axis limits
+ yReset (optional = True): bool
+ Whether to reset the y-axis limits
+ """
self.showFid() # plot the data
self.plotReset(xReset, yReset) # reset the axes limits
def fixAxes(self, axes):
+ """
+ Fixes the axes.
+
+ Parameters
+ ----------
+ axes: list
+ List of the axes indexes that should be changed.
+
+ Returns
+ -------
+ list:
+ The new axis list
+ """
if len(axes) != self.NDIM_PLOT:
fullAxes = np.arange(self.data.ndim())
fullAxes = np.delete(fullAxes, axes)
diff = self.NDIM_PLOT - len(axes)
return np.append(fullAxes[-diff:], axes[-self.NDIM_PLOT:])
- else:
- return axes
+ return axes
def rename(self, name):
+ """
+ Rename the data set.
+
+ Parameters
+ ----------
+ name: str
+ The new name
+ """
self.data.rename(name)
if self.viewSettings['showTitle']:
self.fig.suptitle(self.data.name)
@@ -207,9 +421,28 @@ def rename(self, name):
self.canvas.draw()
def copyCurrent(self, root, fig, canvas, data):
+ """
+ Make a copy of the current data structure and the
+ associated canvas and axis information.
+
+ Parameters
+ ----------
+ root: main1d window class
+ fig: matplotlib figure
+ canvas: matplotlib figure canvas
+ data: spectrum class instance
+ """
return Current1D(root, fig, canvas, data, self)
- def upd(self): # get new data from the data instance
+ def upd(self):
+ """
+ Get new data from the data instance.
+
+ Returns
+ -------
+ bool:
+ True if update was OK
+ """
if self.data.ndim() <= self.axes[-1]:
self.axes = np.array([len(self.data.shape()) - 1])
if len(self.locList) != self.data.ndim():
@@ -225,7 +458,19 @@ def upd(self): # get new data from the data instance
self.viewSettings["ppm"][-1] = False
return True
- def setSlice(self, axes, locList): # change the slice
+ def setSlice(self, axes, locList):
+ """
+ Change the slice
+
+ Parameters
+ ----------
+ axes: ndarray
+ List of the axes along which the data is plot
+ (contains a single entry for this 1D plot)
+ locList: list
+ List with the location (i.e. data positions) of each dimension
+ of the data.
+ """
axesSame = True
if not np.array_equal(self.axes, axes):
axesSame = False
@@ -237,17 +482,48 @@ def setSlice(self, axes, locList): # change the slice
self.plotReset()
def resetLocList(self):
+ """
+ Resets the locations (i.e. data positions) of all dimensions.
+ Default values are [0] for all dimensions.
+ """
self.locList = [0] * self.data.ndim()
def getSelect(self):
+ """
+ Get thew slice operator to construct the 1D data from the total
+ data.
+
+ Returns
+ -------
+ ndarray:
+ Object array with the slices for each dimension.
+ """
tmp = np.array(self.locList, dtype=object)
tmp[self.axes] = slice(None)
return tmp
def setGrids(self, grids):
+ """
+ Turn the plot grid along x and y axis on or off.
+
+ Parameters
+ ----------
+ grids: list of booleans
+ [xgrid,ygrid]
+ """
self.viewSettings["grids"] = grids
def setDiagonal(self, diagonalBool=None, diagonalMult=None):
+ """
+ Change the plotting of a diagonal line in a 2D plot.
+
+ Parameters
+ ----------
+ diagonalBool (optional = None): bool
+ True if diagonal should be plot
+ diagonalMult (optional = None): float
+ Multiplier of the diagonal.
+ """
if diagonalBool is not None:
self.viewSettings["diagonalBool"] = diagonalBool
if diagonalMult is not None:
@@ -255,51 +531,100 @@ def setDiagonal(self, diagonalBool=None, diagonalMult=None):
self.showFid()
def reload(self, *args):
+ """
+ Reloads the data, updates and resets the plot.
+ """
self.data.reload()
self.upd()
self.showFid()
self.plotReset()
self.root.addMacro(['reload'])
-
+
def isComplex(self, *args):
+ """
+ Checks if an axis is complex. The last axis (direct dimension) is always complex.
+ """
return self.data.isComplex(*args)
- def setNoUndo(self,val):
+ def setNoUndo(self, val):
+ """
+ Sets the 'no undo' flag. When this flag is enabled
+ no undo information is saved.
+
+ Parameters
+ ----------
+ val: bool
+ The no undo flag
+ """
self.root.addMacro(['setNoUndo', (val,)])
self.data.setNoUndo(val)
def real(self, *args):
+ """
+ Takes the real value along the current axis.
+ """
self.root.addMacro(['real', (self.axes[-1] - self.data.ndim(), )])
self.data.real(self.axes[-1])
self.upd()
self.showFid()
-
+
def imag(self, *args):
+ """
+ Takes the imaginary value along the current axis.
+ """
self.root.addMacro(['imag', (self.axes[-1] - self.data.ndim(), )])
self.data.imag(self.axes[-1])
self.upd()
self.showFid()
-
+
def abs(self, *args):
+ """
+ Takes the absolute value along the current axis.
+ """
self.root.addMacro(['abs', (self.axes[-1] - self.data.ndim(), )])
self.data.abs(self.axes[-1])
self.upd()
self.showFid()
def conj(self, *args):
+ """
+ Takes the complex conjugate value along the current axis.
+ """
self.root.addMacro(['conj', (self.axes[-1] - self.data.ndim(), )])
self.data.conj(self.axes[-1])
self.upd()
self.showFid()
-
- def setPhaseInter(self, phase0in, phase1in): # interactive changing the phase without editing the actual data
+
+ def setPhaseInter(self, phase0in, phase1in):
+ """
+ Interactive changing the phase without editing the actual data.
+
+ Parameters
+ ----------
+ phase0in: float
+ The 0th order phase
+ phase1in: float
+ The 1st order phase
+ """
phase0 = float(phase0in)
phase1 = float(phase1in)
self.data1D.phase(phase0, phase1, -1)
self.showFid()
self.upd()
- def applyPhase(self, phase0, phase1, select=False): # apply the phase to the actual data
+ def applyPhase(self, phase0, phase1, select=False):
+ """
+ Phase the data.
+
+ Parameters
+ ----------
+ phase0in: float
+ The 0th order phase
+ phase1in: float
+ The 1st order phase
+ select (optional = False): bool
+ If true, apply only for current slice
+ """
phase0 = float(phase0)
phase1 = float(phase1)
if select:
@@ -312,13 +637,20 @@ def applyPhase(self, phase0, phase1, select=False): # apply the phase to the ac
self.showFid()
def correctDFilter(self):
- #Corrects the digital filter via first order phasing
+ """
+ Corrects the digital filter via first order phasing.
+ The filter value (if any) is set upon loading the data.
+ """
self.root.addMacro(['correctDFilter', (self.axes[-1] - self.data.ndim(),)])
self.data.correctDFilter(self.axes[-1])
self.upd()
self.showFid()
- def complexFourier(self): # fourier the actual data and replot
+ def complexFourier(self):
+ """
+ Complex Fourier transform along the current axis.
+ Redraw the plot.
+ """
self.root.addMacro(['complexFourier', (self.axes[-1] - self.data.ndim(), )])
self.data.complexFourier(self.axes[-1])
self.upd()
@@ -327,7 +659,11 @@ def complexFourier(self): # fourier the actual data and replot
self.showFid()
self.plotReset()
- def realFourier(self): # fourier the real data and replot
+ def realFourier(self):
+ """
+ Real Fourier transform along the current axis.
+ Redraw the plot.
+ """
self.root.addMacro(['realFourier', (self.axes[-1] - self.data.ndim(), )])
self.data.realFourier(self.axes[-1])
self.upd()
@@ -337,12 +673,44 @@ def realFourier(self): # fourier the real data and replot
self.plotReset()
def fftshift(self, inv=False): # fftshift the actual data and replot
+ """
+ fftshift along the current axis.
+ Redraw the plot.
+
+ Parameters
+ ----------
+ inv: bool
+ True if inverse shift, False if normal.
+ """
self.root.addMacro(['fftshift', (self.axes[-1] - self.data.ndim(), inv)])
self.data.fftshift(self.axes[-1], inv)
self.upd()
self.showFid()
- def apodPreview(self, lor=None, gauss=None, cos2= [None, None], hamming=None, shift=0.0, shifting=0.0, shiftingAxis=None): # display the 1D data including the apodization function
+ def apodPreview(self, lor=None, gauss=None, cos2=None, hamming=None, shift=0.0, shifting=0.0, shiftingAxis=None):
+ """
+ Preview the effect of apodization without touching the data structure.
+
+ Parameters
+ ----------
+ lor (optional = None): float
+ Lorentzian broadening in Hz
+ gauss (optional = None): float
+ Gaussian broadening in Hz
+ cos2 (optional = [None, None]): list
+ List of floats. The first value is the frequency (two times the number of periods in the time domain).
+ The second value is the phase shift in degrees.
+ hamming (optional = None): float
+ Hamming apodization frequency
+ shift (optional = 0.0): float
+ The amount of time shift to the function (positive is to the right).
+ shifting (optional = 0.0): float
+ A shift in time of the function as a function of the x-axis values along shiftingAxis.
+ shiftingAxis (optional = None): int
+ The dimension for the shifting.
+ """
+ if cos2 is None:
+ cos2 = [None, None]
y = self.data1D.data.copy()
preview = True
if shiftingAxis is None:
@@ -363,7 +731,32 @@ def apodPreview(self, lor=None, gauss=None, cos2= [None, None], hamming=None, sh
self.showFid(y)
self.upd()
- def applyApod(self, lor=None, gauss=None, cos2= [None,None], hamming=None, shift=0.0, shifting=0.0, shiftingAxis=0, select=False): # apply the apodization to the actual data
+ def applyApod(self, lor=None, gauss=None, cos2=None, hamming=None, shift=0.0, shifting=0.0, shiftingAxis=0, select=False): # apply the apodization to the actual data
+ """
+ Apply apodization effects.
+
+ Parameters
+ ----------
+ lor (optional = None): float
+ Lorentzian broadening in Hz
+ gauss (optional = None): float
+ Gaussian broadening in Hz
+ cos2 (optional = [None, None]): list
+ List of floats. The first value is the frequency (two times the number of periods in the time domain).
+ The second value is the phase shift in degrees.
+ hamming (optional = None): float
+ Hamming apodization frequency
+ shift (optional = 0.0): float
+ The amount of time shift to the function (positive is to the right).
+ shifting (optional = 0.0): float
+ A shift in time of the function as a function of the x-axis values along shiftingAxis.
+ shiftingAxis (optional = None): int
+ The dimension for the shifting.
+ select (optional = False): boolean
+ If True, apply only to the current slice.
+ """
+ if cos2 is None:
+ cos2 = [None, None]
if select:
selectSlice = self.getSelect()
else:
@@ -374,18 +767,45 @@ def applyApod(self, lor=None, gauss=None, cos2= [None,None], hamming=None, shift
self.showFid()
def setFreq(self, freq, sw): # set the frequency of the actual data
+ """
+ Set the center frequency and spectral width (sweep width).
+
+ Parameters
+ ----------
+ freq: float
+ Center frequency in Hz
+ sw: float
+ Spectral width in Hz
+
+ """
self.root.addMacro(['setFreq', (freq, sw, self.axes[-1] - self.data.ndim())])
self.data.setFreq(freq, sw, self.axes[-1])
self.upd()
self.showFid()
- def scaleSw(self,scale):
+ def scaleSw(self, scale):
+ """
+ Scale the spectral width (sweep width).
+
+ Parameters
+ ----------
+ scale: float
+ The multiplier
+ """
self.root.addMacro(['scaleSw', (scale, self.axes[-1] - self.data.ndim())])
self.data.scaleSw(scale, self.axes[-1])
self.upd()
self.showFid()
- def setRef(self, ref): # set the frequency of the actual data
+ def setRef(self, ref):
+ """
+ Set the reference frequency (0 Hz position).
+
+ Parameters
+ ----------
+ ref: float
+ The reference frequency
+ """
oldref = self.ref()
self.root.addMacro(['setRef', (ref, self.axes[-1] - self.data.ndim())])
self.data.setRef(ref, self.axes[-1])
@@ -403,6 +823,17 @@ def setRef(self, ref): # set the frequency of the actual data
self.showFid()
def regrid(self, limits, numPoints):
+ """
+ Regrind along the current dimension. This creates a new x-axis, and interpolates to
+ construct the new y-values.
+
+ Parameters
+ ----------
+ limits: list
+ List with the minimum and maximum position of the new x-axis (in Hz).
+ numPoints: int
+ Number of points in the new x-axis
+ """
self.root.addMacro(['regrid', (limits, numPoints, self.axes[-1] - self.data.ndim())])
self.data.regrid(limits, numPoints, self.axes[-1])
self.upd()
@@ -410,6 +841,25 @@ def regrid(self, limits, numPoints):
self.plotReset()
def SN(self, minNoise, maxNoise, minPeak, maxPeak):
+ """
+ Get the signal-to-noise ratio of a specific region.
+
+ Parameters
+ ----------
+ minNoise: int
+ Minimum position of the noise region.
+ maxNoise: int
+ Maximum position of the noise region.
+ minPeak: int
+ Minimum position of the region with the peak inside.
+ maxPeak: int
+ Maximum position of the region with the peak inside.
+
+ Returns
+ -------
+ float:
+ The SNR
+ """
minN = min(minNoise, maxNoise)
maxN = max(minNoise, maxNoise)
minP = min(minPeak, maxPeak)
@@ -417,9 +867,38 @@ def SN(self, minNoise, maxNoise, minPeak, maxPeak):
tmpData = self.data1D.getHyperData(0)
tmpData = tmpData[(0,)*(self.ndim()-1) + (slice(None), )]
tmpData = np.real(self.getDataType(tmpData))
- return (np.max(tmpData[minP:maxP]) / (np.std(tmpData[minN:maxN])))
+ return np.max(tmpData[minP:maxP]) / (np.std(tmpData[minN:maxN]))
def fwhm(self, minPeak, maxPeak, level, unitType=None):
+ """
+ Get the Full Width at Half Maximum (FWHM) for a peak in
+ a specific region. The level can be pout in by the user,
+ so a level of 0.5 will give the FWHM, while other values
+ report the width at other heights.
+
+ Parameters
+ ----------
+ minPeak: int
+ Minimum position of the region with the peak inside.
+ maxPeak: int
+ Maximum position of the region with the peak inside.
+ level: float
+ The level for which the width is to be calculated. For
+ the half width, this should be 0.5.
+ unitType (optional = None): int
+ The unit type, only needs to be supplied when the type should
+ be different than in the current plot.
+ 0: Hz
+ 1: kHz
+ 2: MHz
+ 3: ppm
+
+ Returns
+ -------
+ float:
+ The width
+ """
+
from scipy.interpolate import UnivariateSpline
if unitType is None:
axType = self.getAxType()
@@ -444,10 +923,32 @@ def fwhm(self, minPeak, maxPeak, level, unitType=None):
right = zeroPos[zeroPos < maxX]
if right.size > 0 and left.size > 0:
return abs(left[0] - right[-1])
- else:
- return 0.0
+ return 0.0
def COM(self, minPeak, maxPeak, unitType=None): # Centre of Mass
+ """
+ Get the centre of mass (COM) for a peak in
+ a specific region.
+
+ Parameters
+ ----------
+ minPeak: int
+ Minimum position of the region with the peak inside.
+ maxPeak: int
+ Maximum position of the region with the peak inside.
+ unitType (optional = None): int
+ The unit type, only needs to be supplied when the type should
+ be different than in the current plot.
+ 0: Hz
+ 1: kHz
+ 2: MHz
+ 3: ppm
+
+ Returns
+ -------
+ float:
+ The centre of mass
+ """
dim = len(minPeak)
ppm = []
axType = []
@@ -470,7 +971,7 @@ def COM(self, minPeak, maxPeak, unitType=None): # Centre of Mass
#Slice data
slc = ()
for i in range(dim):
- slc = slc + (slice(minPeak[-(i+1)],maxPeak[-(i+1)],None),)
+ slc = slc + (slice(minPeak[-(i+1)], maxPeak[-(i+1)], None),)
tmpData = tmpData[slc]
COM = []
axes = list(range(dim))
@@ -479,12 +980,33 @@ def COM(self, minPeak, maxPeak, unitType=None): # Centre of Mass
del sumAxes[-(i+1)]
tmpAxis = self.xax(-(i+1))
tmpAxis = tmpAxis[minPeak[i]:maxPeak[i]] * self.getAxMult(self.spec(-(i+1)), axType[i], ppm[i], self.freq(-(i+1)), self.ref(-(i+1)))
- tmpDataNew = np.sum(tmpData,tuple(sumAxes))
+ tmpDataNew = np.sum(tmpData, tuple(sumAxes))
# COM = 1/M *sum(m_i * r_i)
COM.append(1.0 / np.sum(tmpDataNew) * np.sum(tmpDataNew * tmpAxis))
return COM
def Integrals(self, minPeak, maxPeak):
+ """
+ Get the integral for a region.
+
+ Parameters
+ ----------
+ minPeak: int
+ Minimum position of the region.
+ maxPeak: int
+ Maximum position of the region.
+
+ Returns
+ -------
+ float:
+ Integral
+ ndarray:
+ The x-axis of the selected range
+ ndarray:
+ The cumulative sum of the y-values of the range
+ float:
+ The absolute maximum of y-values
+ """
dim = len(minPeak)
for i in range(dim): #Check max > min
if minPeak[i] > maxPeak[i]:
@@ -495,14 +1017,14 @@ def Integrals(self, minPeak, maxPeak):
totShape = tmpData.shape
tmpData = np.real(self.getDataType(tmpData))
maxim = np.max(np.abs(tmpData))
- tmpAxis = tmpAxis[minPeak[0]:maxPeak[0]+1]
+ tmpAxis = tmpAxis[minPeak[0]:maxPeak[0]+1]
slc = tuple()
for i in reversed(range(dim)): #Make slice operator along all dimensions
- slc = slc + (slice(minPeak[i],maxPeak[i] + 1), )
+ slc = slc + (slice(minPeak[i],maxPeak[i] + 1),)
tmpData = tmpData[slc] #slice data
- if self.spec() == 0 and dim ==1:
+ if self.spec() == 0 and dim == 1:
intSum = np.cumsum(tmpData)
- elif self.spec() == 1 and dim ==1:
+ elif self.spec() == 1 and dim == 1:
intSum = np.cumsum(tmpData[-1::-1])[-1::-1]
else:
intSum = None
@@ -515,6 +1037,23 @@ def Integrals(self, minPeak, maxPeak):
return inte, tmpAxis, intSum, maxim
def MaxMin(self, minPeak, maxPeak, type='max'):
+ """
+ Get the maximum or minimum value of a region.
+
+ Parameters
+ ----------
+ minPeak: int
+ Minimum position of the region.
+ maxPeak: int
+ Maximum position of the region.
+ type (optional = 'max'): str
+ 'max' or 'min'
+
+ Returns
+ -------
+ float:
+ The min/max value of the region
+ """
minP = min(minPeak, maxPeak)
maxP = max(minPeak, maxPeak)
tmpData = self.data1D.getHyperData(0)
@@ -522,23 +1061,47 @@ def MaxMin(self, minPeak, maxPeak, type='max'):
tmpData = np.real(self.getDataType(tmpData))
if type == 'max':
return np.max(tmpData[minP:maxP])
- elif type == 'min':
+ if type == 'min':
return np.min(tmpData[minP:maxP])
def integralsPreview(self, x, y, maxim):
+ """
+ Plot preview lines for the integrals tool.
+
+ Parameters
+ ----------
+ x: list of ndarrays
+ x-values of the extra lines
+ y: list of ndarrays
+ y-values of the extra lines
+ maxim: float
+ Maximum values the each integrated regions
+
+ """
xNew = []
yNew = []
scale = 0
- for num in range(len(x)):
+ for num, _ in enumerate(x):
if x[num] is not None and y[num] is not None:
xNew.append(x[num])
yNew.append(y[num])
- scale = np.max([scale,abs(yNew[-1][0]),abs(yNew[-1][-1])])
- for num in range(len(yNew)):
+ scale = np.max([scale, abs(yNew[-1][0]), abs(yNew[-1][-1])])
+ for num, _ in enumerate(yNew):
yNew[num] = yNew[num] / scale * maxim
self.showFid(extraX=xNew, extraY=yNew, extraColor=['g'])
- def resizePreview(self, size, pos): # set size only on local data
+ def resizePreview(self, size, pos):
+ """
+ Preview a resizing (zero filling) operation on the data.
+
+ Parameters
+ ----------
+ size: int
+ The new number of data points
+ pos: int
+ The position where any data points should be inserted
+ or removed.
+ """
self.data1D.resize(size, pos, -1)
self.showFid()
if not self.spec():
@@ -546,6 +1109,17 @@ def resizePreview(self, size, pos): # set size only on local data
self.upd()
def resize(self, size, pos): # set size to the actual data
+ """
+ Apply a resizing (zero filling) operation on the data.
+
+ Parameters
+ ----------
+ size: int
+ The new number of data points
+ pos: int
+ The position where any data points should be inserted
+ or removed.
+ """
self.root.addMacro(['resize', (size, pos, self.axes[-1] - self.data.ndim())])
self.data.resize(size, pos, self.axes[-1])
self.upd()
@@ -554,6 +1128,21 @@ def resize(self, size, pos): # set size to the actual data
self.plotReset(True, False)
def lpsvd(self, nPredict, maxFreq, forward, numPoints):
+ """
+ Apply linear prediction on the data. Both forward and backwards predictions
+ are supported.
+
+ Parameters
+ ----------
+ nPredict : int
+ The number of datapoints to predict.
+ maxFreq : int
+ The maximum number of frequencies to take from the SVD.
+ forward : bool
+ If True, a forward prediction is performed, otherwise a backward prediction is performed.
+ numPoints : int, optional
+ The number of points to use for SVD.
+ """
self.root.addMacro(['lpsvd', (nPredict, maxFreq, forward, numPoints, self.axes[-1] - self.data.ndim())])
self.data.lpsvd(nPredict, maxFreq, forward, numPoints, self.axes[-1])
self.upd()
@@ -561,7 +1150,15 @@ def lpsvd(self, nPredict, maxFreq, forward, numPoints):
if not self.spec():
self.plotReset(True, False)
- def setSpec(self, val): # change from time to freq domain of the actual data
+ def setSpec(self, val):
+ """
+ Change the time/spectrum domain type of the current dimension.
+
+ Parameters
+ ----------
+ val: bool
+ True: spectrum, False: FID
+ """
self.root.addMacro(['setSpec', (val, self.axes[-1] - self.data.ndim())])
self.data.setSpec(val, self.axes[-1])
self.upd()
@@ -571,23 +1168,59 @@ def setSpec(self, val): # change from time to freq domain of the actual data
self.plotReset()
def swapEcho(self, idx):
+ """
+ Apply a swap echo operation.
+
+ Parameters
+ ----------
+ idx: int
+ Position where the swap should occur.
+ """
self.root.addMacro(['swapEcho', (idx, self.axes[-1] - self.data.ndim())])
self.data.swapEcho(idx, self.axes[-1])
self.upd()
self.showFid()
def swapEchoPreview(self, idx):
+ """
+ Preview a swap echo operation.
+
+ Parameters
+ ----------
+ idx: int
+ Position where the swap should occur.
+ """
self.data1D.swapEcho(idx, -1)
self.showFid()
self.upd()
def setWholeEcho(self, value):
+ """
+ Set the Whole Echo toggle for the current dimension.
+
+ Parameters
+ ----------
+ value: bool
+ The new Whole Echo value
+ """
valBool = value != 0
self.root.addMacro(['setWholeEcho', (valBool, self.axes[-1] - self.data.ndim())])
self.data.setWholeEcho(valBool, self.axes[-1])
self.upd()
def shift(self, shift, select=False):
+ """
+ Shifts the data along the current dimension.
+ Shifting is always done in the time domain (i.e. is the current data is a spectrum
+ it is Fourier transformed back and forward to do the shift).
+
+ Parameters
+ ----------
+ shift: int
+ The amount of data points to shift (negative is left shift, positive right shift)
+ select (optional = False): boolean
+ If True, apply only to the current slice.
+ """
if select:
selectSlice = self.getSelect()
else:
@@ -598,11 +1231,29 @@ def shift(self, shift, select=False):
self.showFid()
def shiftPreview(self, shift):
+ """
+ Shows a preview of the shift data operation.
+
+ Parameters
+ ----------
+ shift: int
+ The amount of data points to shift (negative is left shift, positive right shift)
+ """
self.data1D.shift(shift, -1)
self.showFid()
self.upd()
def roll(self, shift, select=False):
+ """
+ Circularly rolls the data along the current dimension. Non-integer shift values are allowed.
+
+ Parameters
+ ----------
+ shift: float
+ The amount of data points to roll (negative is left roll, positive right roll)
+ select (optional = False): boolean
+ If True, apply only to the current slice.
+ """
if select:
selectSlice = self.getSelect()
else:
@@ -613,36 +1264,108 @@ def roll(self, shift, select=False):
self.showFid()
def rollPreview(self, shift):
+ """
+ Shows a preview of the roll data operation.
+
+ Parameters
+ ----------
+ shift: float
+ The amount of data points to roll (negative is left roll, positive right roll)
+ """
self.data1D.roll(shift, -1)
self.showFid()
self.upd()
def align(self, pos1, pos2):
+ """
+ Aligns the maximum of each slice along this dimension, within the pos1-pos2 region.
+
+
+ Parameters
+ ----------
+ pos1: int
+ First data position.
+ pos2: int
+ Second data position.
+ """
self.root.addMacro(['align', (pos1, pos2, self.axes[-1] - self.data.ndim())])
self.data.align(pos1, pos2, self.axes[-1])
self.upd()
self.showFid()
def getdcOffset(self, pos1, pos2):
+ """
+ Gets the average (i.e. DC offset) of a selected region.
+
+ Parameters
+ ----------
+ pos1: int
+ First data position.
+ pos2: int
+ Second data position.
+
+ Returns
+ -------
+ complex value:
+ The offset value
+ """
minPos = int(min(pos1, pos2))
maxPos = int(max(pos1, pos2))
if minPos != maxPos:
tmpData = self.data1D.data[(len(self.shape()) - 1) * (slice(None), ) + (slice(minPos, maxPos), )]
return np.mean(tmpData.getHyperData(0))
- else:
- return 0
+ return 0
def dcOffset(self, offset):
+ """
+ Corrects the DC offset (i.e. subtracts the offset value from all data points).
+
+ Parameters
+ ----------
+ offset: complex value
+ The amount of offset that is to be subtracted.
+ """
self.data1D.subtract([offset])
self.showFid()
self.upd()
def baselinePolyFit(self, x, data, bArray, degree):
+ """
+ Fit a polynomial through the selected data.
+
+ Parameters
+ ----------
+ x: ndarray
+ The x-axis
+ data: ndarray
+ The data along this slice
+ bArray: ndarray, boolian
+ The points that should be used
+ degree: int
+ Number of polynomial orders
+
+ Returns
+ -------
+ ndarray:
+ The fitted polynomial
+ """
import numpy.polynomial.polynomial as poly
polyCoeff = poly.polyfit(x[bArray], data[bArray], degree)
return poly.polyval(x, polyCoeff)
- def baselineCorrectionAll(self, degree, removeList, select=False, invert=False):
+ def baselineCorrectionAll(self, degree, removeList, invert=False):
+ """
+ Correct baseline of a series of data
+
+ Parameters
+ ----------
+ degree: int
+ Polynomial degree
+ removeList: list
+ Indexes of points not include in polyfit
+ invert (optional = False): boolean
+ If True, the removeList is treated as an include list (i.e. inverting the selection)
+ """
tmpAx = np.arange(self.len())
bArray = np.array([True] * self.len())
for i in range(int(np.floor(len(removeList) / 2.0))):
@@ -653,10 +1376,24 @@ def baselineCorrectionAll(self, degree, removeList, select=False, invert=False):
bArray = np.logical_not(bArray)
y = np.apply_along_axis(lambda data: self.baselinePolyFit(self.xax(), data, bArray, degree), self.axes[-1], self.data.getHyperData(0))
y = np.real(self.getDataType(y))
- self.root.addMacro(['subtract', (y)])
+ self.root.addMacro(['subtract', (y,)])
self.data.subtract(y)
def baselineCorrection(self, degree, removeList, select=False, invert=False):
+ """
+ Correct baseline of spectrum/fid.
+
+ Parameters
+ ----------
+ degree: int
+ Polynomial degree
+ removeList: list
+ Indexes of points not include in polyfit
+ select (optional = False): boolean
+ If True, apply only to the current slice.
+ invert (optional = False): boolean
+ If True, the removeList is treated as an include list (i.e. inverting the selection)
+ """
if select:
selectSlice = self.getSelect()
else:
@@ -677,6 +1414,18 @@ def baselineCorrection(self, degree, removeList, select=False, invert=False):
self.data.baselineCorrection(y, self.axes[-1], select=selectSlice)
def previewBaselineCorrection(self, degree, removeList, invert=False):
+ """
+ Preview the baseline correction of a spectrum/fid.
+
+ Parameters
+ ----------
+ degree: int
+ Polynomial degree
+ removeList: list
+ Indexes of points not include in polyfit
+ invert (optional = False): boolean
+ If True, the removeList is treated as an include list (i.e. inverting the selection)
+ """
tmpData = self.data1D.getHyperData(0)
tmpData = tmpData[(0,)*(self.ndim()-1) + (slice(None), )]
tmpAx = np.arange(self.len())
@@ -701,6 +1450,16 @@ def previewBaselineCorrection(self, degree, removeList, invert=False):
self.upd()
def previewRemoveList(self, removeList, invert=False):
+ """
+ Preview the removelist of a baseline correction.
+
+ Parameters
+ ----------
+ removeList: list
+ Indexes of points not include in polyfit
+ invert (optional = False): boolean
+ If True, the removeList is treated as an include list (i.e. inverting the selection)
+ """
axMult = self.getAxMult(self.spec(), self.getAxType(), self.getppm(), self.freq(), self.ref())
self.resetPreviewRemoveList()
lineColor = 'r'
@@ -714,69 +1473,211 @@ def previewRemoveList(self, removeList, invert=False):
self.canvas.draw()
def resetPreviewRemoveList(self):
+ """
+ Resets the preview remove list of the baseline correction.
+ """
if hasattr(self, 'removeListLines'):
for i in self.removeListLines:
i.remove()
self.removeListLines = []
def states(self):
+ """
+ Performs a States data conversion along the current dimension.
+ """
self.root.addMacro(['states', (self.axes[-1] - self.data.ndim(), )])
self.data.states(self.axes[-1])
self.upd()
self.showFid()
def statesTPPI(self):
+ """
+ Performs a States-TPPI data conversion along the current dimension.
+ """
self.root.addMacro(['statesTPPI', (self.axes[-1] - self.data.ndim(), )])
self.data.statesTPPI(self.axes[-1])
self.upd()
self.showFid()
def echoAntiEcho(self):
+ """
+ Performs an Echo-Antiecho data conversion along the current dimension.
+ """
self.root.addMacro(['echoAntiEcho', (self.axes[-1] - self.data.ndim(), )])
self.data.echoAntiEcho(self.axes[-1])
self.upd()
self.showFid()
def matrixFuncs(self, func, name, pos1, pos2, newSpec=False):
+ """
+ Function that handles multiple matrix operations.
+
+ name: str
+ Name of operation: integrate, sum, max, min, argmax, argmin, averge
+ pos1: int
+ First data point limit of the selected region.
+ pos2: int
+ Second data point limit of the selected region.
+ newSpec (optional = False): boolean
+ If True, a new spectrum class is returned, holding the output of the matrix function.
+
+ Returns
+ -------
+ Spectrum object:
+ If newSpec is True, a new spectrum object is returned.
+ """
if newSpec:
tmpData = copy.deepcopy(self.data)
func(tmpData, pos1, pos2, self.axes[-1])
return tmpData
- else:
- self.root.addMacro([name, (pos1, pos2, self.axes[-1] - self.data.ndim(), )])
- func(self.data, pos1, pos2, self.axes[-1])
- if self.upd():
- self.showFid()
- self.plotReset()
-
+ self.root.addMacro([name, (pos1, pos2, self.axes[-1] - self.data.ndim(), )])
+ func(self.data, pos1, pos2, self.axes[-1])
+ if self.upd():
+ self.showFid()
+ self.plotReset()
+
def integrate(self, pos1, pos2, newSpec=False):
+ """
+ Integrate all slices over the selected region.
+
+ Parameters
+ ----------
+ pos1: int
+ First data point limit of the selected region.
+ pos2: int
+ Second data point limit of the selected region.
+ newSpec (optional = False): boolean
+ If True, a new spectrum class is returned, holding the output of the matrix function.
+
+ Returns
+ -------
+ Spectrum object:
+ If newSpec is True, a new spectrum object is returned. Else, 'None' is returned.
+ """
return self.matrixFuncs(lambda obj, *args: obj.integrate(*args), 'integrate', pos1, pos2, newSpec)
def sum(self, pos1, pos2, newSpec=False):
return self.matrixFuncs(lambda obj, *args: obj.sum(*args), 'sum', pos1, pos2, newSpec)
-
+
def max(self, pos1, pos2, newSpec=False):
+ """
+ Get the maximum of all slices over the selected region.
+
+ Parameters
+ ----------
+ pos1: int
+ First data point limit of the selected region.
+ pos2: int
+ Second data point limit of the selected region.
+ newSpec (optional = False): boolean
+ If True, a new spectrum class is returned, holding the output of the matrix function.
+
+ Returns
+ -------
+ Spectrum object:
+ If newSpec is True, a new spectrum object is returned. Else, 'None' is returned.
+ """
return self.matrixFuncs(lambda obj, *args: obj.max(*args), 'max', pos1, pos2, newSpec)
def min(self, pos1, pos2, newSpec=False):
+ """
+ Get the minimum of all slices over the selected region.
+
+ Parameters
+ ----------
+ pos1: int
+ First data point limit of the selected region.
+ pos2: int
+ Second data point limit of the selected region.
+ newSpec (optional = False): boolean
+ If True, a new spectrum class is returned, holding the output of the matrix function.
+
+ Returns
+ -------
+ Spectrum object:
+ If newSpec is True, a new spectrum object is returned. Else, 'None' is returned.
+ """
return self.matrixFuncs(lambda obj, *args: obj.min(*args), 'min', pos1, pos2, newSpec)
def argmax(self, pos1, pos2, newSpec=False):
+ """
+ Get the arg maxmimum of all slices over the selected region.
+
+ Parameters
+ ----------
+ pos1: int
+ First data point limit of the selected region.
+ pos2: int
+ Second data point limit of the selected region.
+ newSpec (optional = False): boolean
+ If True, a new spectrum class is returned, holding the output of the matrix function.
+
+ Returns
+ -------
+ Spectrum object:
+ If newSpec is True, a new spectrum object is returned. Else, 'None' is returned.
+ """
return self.matrixFuncs(lambda obj, *args: obj.argmax(*args), 'argmax', pos1, pos2, newSpec)
def argmin(self, pos1, pos2, newSpec=False):
+ """
+ Get the arg minimum of all slices over the selected region.
+
+ Parameters
+ ----------
+ pos1: int
+ First data point limit of the selected region.
+ pos2: int
+ Second data point limit of the selected region.
+ newSpec (optional = False): boolean
+ If True, a new spectrum class is returned, holding the output of the matrix function.
+
+ Returns
+ -------
+ Spectrum object:
+ If newSpec is True, a new spectrum object is returned. Else, 'None' is returned.
+ """
return self.matrixFuncs(lambda obj, *args: obj.argmin(*args), 'argmin', pos1, pos2, newSpec)
def average(self, pos1, pos2, newSpec=False):
+ """
+ Get the average of all slices over the selected region.
+
+ Parameters
+ ----------
+ pos1: int
+ First data point limit of the selected region.
+ pos2: int
+ Second data point limit of the selected region.
+ newSpec (optional = False): boolean
+ If True, a new spectrum class is returned, holding the output of the matrix function.
+
+ Returns
+ -------
+ Spectrum object:
+ If newSpec is True, a new spectrum object is returned. Else, 'None' is returned.
+ """
return self.matrixFuncs(lambda obj, *args: obj.average(*args), 'average', pos1, pos2, newSpec)
def flipLR(self):
+ """
+ Flip (i.e. mirror) the data over the x-axis.
+ """
self.data.flipLR(self.axes[-1])
self.upd()
self.showFid()
self.root.addMacro(['flipLR', (self.axes[-1] - self.data.ndim(), )])
def concatenate(self, axes):
+ """
+ Concatenate the data along an input axis.
+
+ Parameters
+ ----------
+ axes: int
+ The concatenation axis
+
+ """
self.data.concatenate(axes)
self.upd()
self.showFid()
@@ -784,6 +1685,14 @@ def concatenate(self, axes):
self.root.addMacro(['concatenate', (axes - self.data.ndim() - 1, )])
def split(self, sections):
+ """
+ Split the data long the current dimension in part
+
+ Parameters
+ ----------
+ sections: int
+ Split in this number of sections.
+ """
self.data.split(sections, self.axes[-1])
self.upd()
self.showFid()
@@ -791,18 +1700,42 @@ def split(self, sections):
self.root.addMacro(['split', (sections, self.axes[-1] - self.data.ndim() + 1)])
def diff(self):
+ """
+ Get the difference between data points along the current dimension.
+ This reduces the size of the data along this dimension by 1.
+
+ Diff is taken from left to right in the fid, but from right to left in the spectrum (i.e. the spectrum is
+ displayed in a mirrored way).
+ """
self.data.diff(self.axes[-1])
self.upd()
self.showFid()
self.root.addMacro(['diff', (self.axes[-1] - self.data.ndim(), )])
def cumsum(self):
+ """
+ Get the cumulative sum of the data points along the current dimension.
+
+ Cumsum is taken from left to right in the fid, but from right to left in the spectrum (i.e. the spectrum is
+ displayed in a mirrored way).
+ """
self.data.cumsum(self.axes[-1])
self.upd()
self.showFid()
self.root.addMacro(['cumsum', (self.axes[-1] - self.data.ndim(), )])
def insert(self, data, pos):
+ """
+ Insert data at a position along the current dimension.
+
+ Parameters
+ ----------
+ data: hypercomplex data class
+ The data to be inserted
+ pos: int
+ Position where the data should be inserted
+ """
+
self.root.addMacro(['insert', (data, pos, self.axes[-1] - self.data.ndim())])
self.data.insert(data, pos, self.axes[-1])
self.upd()
@@ -810,17 +1743,43 @@ def insert(self, data, pos):
self.plotReset()
def delete(self, pos):
+ """
+ Delete the data from specified positions along the current dimension.
+
+ Parameters
+ ----------
+ pos: int or array_like
+ The indices to remove.
+ """
self.data.delete(pos, self.axes[-1])
self.upd()
self.showFid()
self.root.addMacro(['delete', (pos, self.axes[-1] - self.data.ndim())])
def deletePreview(self, pos):
+ """
+ Preview the delete operation.
+
+ Parameters
+ ----------
+ pos: int or array_like
+ The indices to remove.
+ """
self.data1D.delete(pos, -1)
self.showFid()
self.upd()
def add(self, data, select=False):
+ """
+ Adds (sums) data to the current data.
+
+ Parameters
+ ----------
+ data: hypercomplex data class
+ The data to be added.
+ select (optional = False): boolean
+ If True, apply only to the current slice.
+ """
if select:
selectSlice = self.getSelect()
else:
@@ -831,6 +1790,16 @@ def add(self, data, select=False):
self.showFid()
def subtract(self, data, select=False):
+ """
+ Subtract data from to the current data.
+
+ Parameters
+ ----------
+ data: hypercomplex data class
+ The data to be subtracted.
+ select (optional = False): boolean
+ If True, apply only to the current slice.
+ """
if select:
selectSlice = self.getSelect()
else:
@@ -841,6 +1810,17 @@ def subtract(self, data, select=False):
self.showFid()
def multiply(self, data, select=False):
+ """
+ Multiply the current data with extra data. Note that a complex data
+ multiplication is used.
+
+ Parameters
+ ----------
+ data: hypercomplex data class
+ The data to be multiplied with.
+ select (optional = False): boolean
+ If True, apply only to the current slice.
+ """
if select:
selectSlice = self.getSelect()
else:
@@ -851,11 +1831,30 @@ def multiply(self, data, select=False):
self.showFid()
def multiplyPreview(self, data):
+ """
+ Preview the multiplication of data to the current data.
+
+ Parameters
+ ----------
+ data: hypercomplex data class
+ The data to be multiplied with.
+ """
self.data1D.multiply(data, -1)
self.showFid()
self.upd()
-
+
def divide(self, data, select=False):
+ """
+ Divide the current data with extra data. Note that a complex data
+ division is used.
+
+ Parameters
+ ----------
+ data: hypercomplex data class
+ The data to be divided with.
+ select (optional = False): boolean
+ If True, apply only to the current slice.
+ """
if select:
selectSlice = self.getSelect()
else:
@@ -866,6 +1865,21 @@ def divide(self, data, select=False):
self.showFid()
def normalize(self, value, scale, type, select=False):
+ """
+ Normalize the data, relative to a selected region.
+ Different types are supported: maximum, minimum, and integral.
+
+ Parameters
+ ----------
+ value: float
+ Value necessary to scale the selected region to 1.
+ scale: float
+ Extra scaling to get to this value
+ type: int
+ 0:, integral. 1: max. 2: min
+ select (optional = False): boolean
+ If True, apply only to the current slice.
+ """
if select:
selectSlice = self.getSelect()
else:
@@ -874,31 +1888,81 @@ def normalize(self, value, scale, type, select=False):
self.data.normalize(value, scale, type, self.axes[-1], select=selectSlice)
self.upd()
self.showFid()
-
+
def subtractAvg(self, pos1, pos2):
+ """
+ Subtract the average of a region off all slices from that slice. This can be used
+ to correct an offset, for example.
+
+ Parameters
+ ----------
+ pos1: int
+ First data point limit of the selected region.
+ pos2: int
+ Second data point limit of the selected region.
+ """
self.root.addMacro(['subtractAvg', (pos1, pos2, self.axes[-1] - self.data.ndim())])
self.data.subtractAvg(pos1, pos2, self.axes[-1])
self.upd()
self.showFid()
def subtractAvgPreview(self, pos1, pos2):
+ """
+ Preview of the effect of the "subtractAvg" function.
+
+ Parameters
+ ----------
+ pos1: int
+ First data point limit of the selected region.
+ pos2: int
+ Second data point limit of the selected region.
+ """
self.data1D.subtractAvg(pos1, pos2, -1)
self.showFid()
self.upd()
def extract(self, pos1, pos2, newSpec=False):
+ """
+ Extract a region from the data (i.e. remove data outside the region.
+ Can return a new data class if newSpec==True.
+
+ Parameters
+ ----------
+ pos1: int
+ First data point limit of the selected region.
+ pos2: int
+ Second data point limit of the selected region.
+ newSpec (optional = False): boolean
+ Return a new data class object
+
+ Returns
+ -------
+ Spectrum object:
+ If newSpec is True, a new spectrum object is returned. Else, 'None' is returned.
+ """
if newSpec:
tmpData = copy.deepcopy(self.data)
tmpData.extract(pos1, pos2, self.axes[-1])
return tmpData
- else:
- self.root.addMacro(['extract', (pos1, pos2, self.axes[-1] - self.data.ndim())])
- self.data.extract(pos1, pos2, self.axes[-1])
- self.upd()
- self.showFid()
- self.plotReset()
+ self.root.addMacro(['extract', (pos1, pos2, self.axes[-1] - self.data.ndim())])
+ self.data.extract(pos1, pos2, self.axes[-1])
+ self.upd()
+ self.showFid()
+ self.plotReset()
def fiddle(self, pos1, pos2, lb):
+ """
+ Do a reference deconvolution using the fiddle algorithm.
+
+ Parameters
+ ----------
+ pos1: int
+ First data point limit of the selected region.
+ pos2: int
+ Second data point limit of the selected region.
+ lb: float
+ Added line broadening (Lorentzian) in Hz. This is needed to avoid artifacts.
+ """
minPos = min(pos1, pos2)
maxPos = max(pos1, pos2)
tmpData = self.data1D.getHyperData(0)
@@ -911,62 +1975,190 @@ def fiddle(self, pos1, pos2, lb):
self.showFid()
def shearing(self, shear, axes, axes2, toRef=False):
+ """
+ Apply a shearing transform to the data.
+
+ Parameters
+ ----------
+ shear: float
+ Shearing constant
+ axes: int
+ The axis number over which the amount of shearing differs.
+ axes2: int
+ The axis over which the data must be rolled.
+ toRef (optional = False): boolean
+ Whether shearing should be relative to the reference (otherwise to the centre of the spectrum)
+ """
self.root.addMacro(['shear', (shear, axes - self.data.ndim(), axes2 - self.data.ndim()), toRef])
self.data.shear(shear, axes, axes2, toRef)
self.upd()
self.showFid()
def reorder(self, pos, newLength):
+ """
+ Reorder the current data to the new positions. Missing points are set to zero, and
+ zeroes are appended to reach 'newLength'.
+
+ Parameters
+ ----------
+ pos: list of ints
+ List with the new positions of each data point
+ newLength: int
+ The new length of the data
+ """
self.root.addMacro(['reorder', (pos, newLength, self.axes[-1] - self.data.ndim())])
self.data.reorder(pos, newLength, self.axes[-1])
self.upd()
self.showFid()
def ffm(self, posList, typeVal):
+ """
+ Apply the Fast Forward Maximum Entropy reconstruction method (for NUS data).
+
+ Parameters
+ ----------
+ pos: list of ints
+ List with the measured (non-zero) positions
+ typeVal : {0, 1, 2}
+ The type of data to be reconstructed.
+ 0=complex, 1=States or States-TPPI, 2=TPPI.
+ """
self.root.addMacro(['ffm', (posList, typeVal, self.axes[-1] - self.data.ndim())])
self.data.ffm(posList, typeVal, self.axes[-1])
self.upd()
self.showFid()
def clean(self, posList, typeVal, gamma, threshold, maxIter):
+ """
+ Apply the CLEAN reconstruction method (for NUS data).
+
+ Parameters
+ ----------
+ posList : array_like
+ A list of indices that are recorded datapoints.
+ All other datapoints will be reconstructed.
+ typeVal : {0, 1, 2}
+ The type of data to be reconstructed.
+ 0=complex, 1=States or States-TPPI, 2=TPPI.
+ gamma : float
+ Gamma value of the CLEAN calculation.
+ threshold : float
+ Stopping limit (0 < x < 1) (stop if residual intensity below this point).
+ maxIter : int
+ Maximum number of iterations.
+ """
self.root.addMacro(['clean', (posList, typeVal, self.axes[-1] - self.data.ndim(), gamma, threshold, maxIter)])
self.data.clean(posList, typeVal, self.axes[-1], gamma, threshold, maxIter)
self.upd()
self.showFid()
def ist(self, posList, typeVal, threshold, maxIter, tracelimit):
+ """
+ Apply the IST (Iterative Soft Thresholding) reconstruction method (for NUS data).
+
+ Parameters
+ ----------
+ posList : array_like
+ A list of indices that are recorded datapoints.
+ All other datapoints will be reconstructed.
+ typeVal : {0, 1, 2}
+ The type of data to be reconstructed.
+ 0=complex, 1=States or States-TPPI, 2=TPPI.
+ threshold : float
+ threshold. The level (0 < x < 1) at which the data is cut every iteration.
+ maxIter : int
+ Maximum number of iterations.
+ tracelimit : float
+ Stopping limit (0 < x < 1) (stop if residual intensity below this point).
+ """
self.root.addMacro(['ist', (posList, typeVal, self.axes[-1] - self.data.ndim(), threshold, maxIter, tracelimit)])
self.data.ist(posList, typeVal, self.axes[-1], threshold, maxIter, tracelimit)
self.upd()
self.showFid()
def autoPhase(self, phaseNum):
+ """
+ Automatically phase the data along the current dimension.
+ This function returns the phasing answers, but does not execute the phasing yet.
+
+ Parameters
+ ----------
+ phaseNum: int
+ Order up to which to perform the autophasing.
+ For 0 only zero order phasing is performed, for 1 both zero and first order phasing is performed.
+
+ Returns
+ -------
+ list:
+ List with 0th and 1st order phase.
+ """
phases = self.data1D.autoPhase(phaseNum, -1, [0]*self.ndim(), returnPhases=True)
self.upd()
return phases
def directAutoPhase(self, phaseNum):
+ """
+ Automatically phase the data along the current dimension.
+ This function applies the phasing directly to the data.
+
+ Parameters
+ ----------
+ phaseNum: int
+ Order up to which to perform the autophasing.
+ For 0 only zero order phasing is performed, for 1 both zero and first order phasing is performed.
+ """
tmpLocList = copy.copy(self.locList)
if self.ndim() > 1:
- tmpLocList[self.axes[:-1]] = self.viewSettings["stackBegin"]
+ if self.viewSettings["stackBegin"] is None:
+ tmpLocList[self.axes[-1]] = 0
+ else:
+ tmpLocList[self.axes[-1]] = self.viewSettings["stackBegin"]
self.root.addMacro(['autoPhase', (phaseNum, self.axes[-1] - self.data.ndim(), tmpLocList)])
self.data.autoPhase(phaseNum, self.axes[-1], tmpLocList)
self.upd()
self.showFid()
def autoPhaseAll(self, phaseNum):
+ """
+ Automatically phase the data along the current dimension, for
+ each trace individually.
+
+ Parameters
+ ----------
+ phaseNum: int
+ Order up to which to perform the autophasing.
+ For 0 only zero order phasing is performed, for 1 both zero and first order phasing is performed.
+ """
self.root.addMacro(['autoPhaseAll', (phaseNum, self.axes[-1] - self.data.ndim())])
self.data.autoPhaseAll(phaseNum, self.axes[-1])
self.upd()
self.showFid()
def setXaxPreview(self, xax):
+ """
+ Preview the plot with a new x-axis.
+
+ Parameters
+ ----------
+ xax : array_like
+ The x-axis.
+ It should have the same length as the size of the data along dimension axis.
+ """
self.data1D.setXax(xax, -1)
self.showFid()
self.plotReset()
self.upd()
def setXax(self, xax):
+ """
+ Change the x-axis of the data.
+
+ Parameters
+ ----------
+ xax : array_like
+ The x-axis.
+ It should have the same length as the size of the data along dimension axis.
+ """
self.root.addMacro(['setXax', (xax, self.axes[-1] - self.data.ndim())])
self.data.setXax(xax, self.axes[-1])
self.upd()
@@ -974,6 +2166,30 @@ def setXax(self, xax):
self.plotReset()
def setAxType(self, val, update=True, num=-1):
+ """
+ Change the axis type if the x-axis.
+
+ The type can be 0,1,2 or 3.
+ For a spectrum axis:
+ 0: Hz
+ 1: kHz
+ 2: MHz
+ 3: ppm
+
+ For an FID axis:
+ 0: s
+ 1: ms
+ 2: us
+
+ Parameters
+ ----------
+ val: int
+ The new axis type
+ update (optional = True): boolean
+ If True, update the displays with the new axis.
+ num (optional = -1): int
+ Which axis to change (default -1 is the x-axis, -2 would be the y axis, etc.)
+ """
oldAxMult = self.getAxMult(self.spec(num), self.getAxType(num), self.getppm(num), self.freq(num), self.ref(num))
if val == 3:
self.viewSettings["ppm"][num] = True
@@ -981,57 +2197,148 @@ def setAxType(self, val, update=True, num=-1):
self.viewSettings["ppm"][num] = False
self.viewSettings["axType"][num] = val
newAxMult = self.getAxMult(self.spec(num), self.getAxType(num), self.getppm(num), self.freq(num), self.ref(num))
- if num == -1 or num == (self.ndim()-1):
+ if num in (-1, self.ndim()-1):
self.xminlim = self.xminlim * newAxMult / oldAxMult
self.xmaxlim = self.xmaxlim * newAxMult / oldAxMult
- elif num == -2 or num == (self.ndim()-2):
+ elif num in (-2, self.ndim()-2):
self.yminlim = self.yminlim * newAxMult / oldAxMult
self.ymaxlim = self.ymaxlim * newAxMult / oldAxMult
if update:
self.showFid()
def hilbert(self):
+ """
+ Apply a Hilbert transform along the current dimension.
+ This reconstructs the imaginary part based on the real part of the data.
+ """
self.root.addMacro(['hilbert', (self.axes[-1] - self.data.ndim(), )])
self.data.hilbert(self.axes[-1])
self.upd()
self.showFid()
def getColorMap(self):
+ """
+ Get the current color map
+
+ Returns
+ -------
+ colormap object
+ """
return COLORMAPLIST.index(self.viewSettings["colorMap"])
def setColorMap(self, num):
+ """
+ Set the color map to an input number.
+
+ Parameters
+ ----------
+ num: int
+ The number of the color map.
+ """
self.viewSettings["colorMap"] = COLORMAPLIST[num]
def getColorRange(self):
+ """
+ Returns the name of the current color range.
+ """
return COLORRANGELIST.index(self.viewSettings["colorRange"])
def setColorRange(self, num):
+ """
+ Set the color range to an input number.
+
+ Parameters
+ ----------
+ num: int
+ The number of the color range.
+ """
self.viewSettings["colorRange"] = COLORRANGELIST[num]
def setColor(self, color):
+ """
+ Set line color.
+
+ Parameters
+ ----------
+ color: string
+ Color string like '#1F77B4'
+ """
self.viewSettings["color"] = color
def setLw(self, lw):
+ """
+ Set the line width of the plot line.
+
+ Parameters
+ lw: float:
+ The new line width
+ """
self.viewSettings["linewidth"] = lw
def setTickNum(self, x, y):
+ """
+ Set suggested minimum number of ticks for the x and y axis.
+
+ Parameters
+ ----------
+ x: int
+ Number of x ticks
+ y: int
+ Number of y ticks
+ """
self.viewSettings["minXTicks"] = x
self.viewSettings["minYTicks"] = y
def setContourColors(self, colors):
+ """
+ Sets the positive/negative colors for the contour plot.
+
+ Parameters
+ ----------
+ colors: list of color strings
+ The positive/negative color string
+ """
self.viewSettings["contourColors"] = colors
def setContourConst(self, constant):
+ """
+ Parameters
+ ----------
+ constant: bool
+ If True, use constant colors for negative/positive contours.
+ If False, use the color gradient
+ """
self.viewSettings["contourConst"] = constant
def getOOM(self):
+ """
+ Get order of magnitude for the intensity of the current data.
+
+ Returns
+ -------
+ int:
+ Order of magnitude
+ """
absVal = np.max(np.abs(self.data.getHyperData(0)))
if absVal == 0.0:
return 1
- else:
- return int(np.floor(np.log10(absVal)))
+ return int(np.floor(np.log10(absVal)))
- def showFid(self, oldData=None, extraX=None, extraY=None, extraColor=None): # display the 1D data
+ def showFid(self, oldData=None, extraX=None, extraY=None, extraColor=None):
+ """
+ Display the data
+
+ Parameters
+ ----------
+ oldData (optional = None): hypercomplex data type
+ The old data, to display under the current (i.e. during apodization).
+ extraX (optional = None): list of ndarrays
+ List of extra x-axes for 1D data curves
+ extray (optional = None): list of ndarrays
+ List of extra intensity data for 1D data curves
+ extraColor (optional = None): list of color strings
+ List of color strings for the extra data
+ """
self.peakPickReset()
tmpdata = self.data1D.getHyperData(0)
self.ax.cla()
@@ -1051,7 +2358,7 @@ def showFid(self, oldData=None, extraX=None, extraY=None, extraColor=None): # d
self.line_ydata_extra.append(tmp)
self.ax.plot(self.line_xdata_extra[-1], self.line_ydata_extra[-1], marker=marker, linestyle=linestyle, c='k', alpha=0.2, linewidth=self.viewSettings["linewidth"], label=self.data.name + '_old', picker=True)
if extraX is not None:
- for num in range(len(extraX)):
+ for num, _ in enumerate(extraX):
self.line_xdata_extra.append(extraX[num] * axMult)
self.line_ydata_extra.append(extraY[num])
if extraColor is None:
@@ -1063,7 +2370,7 @@ def showFid(self, oldData=None, extraX=None, extraY=None, extraColor=None): # d
color = extraColor[num]
self.ax.plot(self.line_xdata_extra[-1], self.line_ydata_extra[-1], marker='', linestyle='-', c=color, linewidth=self.viewSettings["linewidth"], picker=True)
tmpdata = self.getDataType(tmpdata)
- if(self.viewSettings["plotType"] == 2):
+ if self.viewSettings["plotType"] == 2:
self.line_xdata.append(self.line_xdata[-1])
self.line_ydata = [np.imag(tmpdata), np.real(tmpdata)]
self.ax.plot(self.line_xdata[-2], self.line_ydata[-2], marker=marker, linestyle=linestyle, c='#FF7F0E', linewidth=self.viewSettings["linewidth"], label=self.data.name + '_imag', picker=True)
@@ -1091,15 +2398,34 @@ def showFid(self, oldData=None, extraX=None, extraY=None, extraColor=None): # d
self.setTicks()
self.canvas.draw()
- def setTicks(self,Xset = True,Yset = True):
+ def setTicks(self, Xset=True, Yset=True):
+ """
+ Set ticks for the current plot.
+
+ Parameters
+ ----------
+ Xset (optional = True): boolean
+ If False, do not draw x-ticks
+ Yset (optional = True): boolean
+ If False, do not draw y-ticks
+ """
if matplotlib.__version__[0] > '1':
if Xset:
- self.ax.xaxis.set_major_locator(ticker.MaxNLocator(nbins='auto', steps=[1,2,2.5,5,10], min_n_ticks=self.viewSettings["minXTicks"]))
+ self.ax.xaxis.set_major_locator(ticker.MaxNLocator(nbins='auto', steps=[1, 2, 2.5, 5, 10], min_n_ticks=self.viewSettings["minXTicks"]))
if Yset:
- self.ax.yaxis.set_major_locator(ticker.MaxNLocator(nbins='auto', steps=[1,2,2.5,5,10], min_n_ticks=self.viewSettings["minYTicks"]))
-
- def plotReset(self, xReset=True, yReset=True): # set the plot limits to min and max values
- showDat = self.data1D.data[0]
+ self.ax.yaxis.set_major_locator(ticker.MaxNLocator(nbins='auto', steps=[1, 2, 2.5, 5, 10], min_n_ticks=self.viewSettings["minYTicks"]))
+
+ def plotReset(self, xReset=True, yReset=True):
+ """
+ Reset plot limits.
+
+ Parameters
+ ----------
+ xReset (optional = True): boolean
+ If True, reset the x-axis limits
+ yReset (optional = True): boolean
+ If True, reset the y-axis limits
+ """
miny = np.min(self.line_ydata)
maxy = np.max(self.line_ydata)
for line in self.line_ydata_extra:
@@ -1157,17 +2483,58 @@ class CurrentMulti(Current1D):
X_RESIZE = False
Y_RESIZE = True
- def setExtraSlice(self, extraNum, axes, locList): # change the slice
+ def setExtraSlice(self, extraNum, axes, locList):
+ """
+ Change the slice of one of the extra data sets
+
+ Parameters
+ ----------
+ extraNum: int
+ Index of the extra data
+ axes: 1darray
+ The new axis
+ locList: list
+ New slice information for this data
+ """
self.viewSettings["extraAxes"][extraNum] = axes
self.viewSettings["extraLoc"][extraNum] = locList
def copyCurrent(self, root, fig, canvas, data):
+ """
+ Make a copy of the current data structure and the
+ associated canvas and axis information.
+
+ Parameters
+ ----------
+ root: main1Dwindow
+ The basic window
+ fig: matplotib figure
+ The figure
+ canvas: matplotlib canvas
+ The plot canvas
+ data: spectrum class instance
+ The data class
+
+ Returns
+ -------
+ CurrentMulti view class
+ """
return CurrentMulti(root, fig, canvas, data, self)
def addExtraData(self, data, name):
+ """
+ Add extra data to the multiview
+
+ Parameters
+ ----------
+ data: spectrum class data
+ The extra data
+ name: str
+ The name of the extra data
+ """
self.viewSettings["extraName"].append(name)
self.viewSettings["extraData"].append(data)
- self.viewSettings["extraLoc"].append([0] * (len(self.viewSettings["extraData"][-1].shape()) ))
+ self.viewSettings["extraLoc"].append([0] * (len(self.viewSettings["extraData"][-1].shape())))
self.viewSettings["extraColor"].append(COLORCONVERTER.to_rgb(COLORCYCLE[np.mod(len(self.viewSettings["extraData"]), len(COLORCYCLE))]['color'])) # find a good color system
self.viewSettings["extraAxes"].append([len(data.shape()) - 1])
self.viewSettings["extraScale"].append(1.0)
@@ -1176,6 +2543,14 @@ def addExtraData(self, data, name):
self.showFid()
def delExtraData(self, num):
+ """
+ Delete extra data
+
+ Parameters
+ ----------
+ num: int
+ Index of the data to be removed.
+ """
del self.viewSettings["extraData"][num]
del self.viewSettings["extraLoc"][num]
del self.viewSettings["extraColor"][num]
@@ -1187,36 +2562,115 @@ def delExtraData(self, num):
self.showFid()
def setExtraColor(self, num, color):
+ """
+ Set the color of a specified extra data set
+
+ Parameters
+ ----------
+ num: int
+ Index of the extra data
+ color: tuple
+ Color tuple (R,G,B,Alpha) of the new color
+ """
self.viewSettings["extraColor"][num] = color
self.showFid()
def getExtraColor(self, num):
+ """
+ Returns the colour tuple for a specified extra data
+
+ Parameters
+ ----------
+ num: int
+ Index of the extra data
+
+ Returns
+ -------
+ tuple:
+ The colour tuple
+ """
return tuple(np.array(255 * np.array(self.viewSettings["extraColor"][num]), dtype=int))
def resetLocList(self):
+ """
+ Resets the location list (slices) of all data.
+ """
super(CurrentMulti, self).resetLocList()
self.resetExtraLocList()
def setExtraScale(self, num, scale):
+ """
+ Set the vertical scaling of additional plotted data.
+
+ Parameters
+ ----------
+ num: int
+ Index of the extra data
+ scale: float
+ The new scaling factor
+ """
self.viewSettings["extraScale"][num] = scale
self.showFid()
def setExtraOffset(self, num, offset):
+ """
+ Set the vertical offset of additional plotted data.
+
+ Parameters
+ ----------
+ num: int
+ Index of the extra data
+ offset: float
+ The new offset
+ """
self.viewSettings["extraOffset"][num] = offset
self.showFid()
def setExtraShift(self, num, shift):
+ """
+ Set the horizontal offset of additional plotted data.
+
+ Parameters
+ ----------
+ num: int
+ Index of the extra data
+ shift: float
+ The new shift in units of the current axis
+ """
self.viewSettings["extraShift"][num] = shift
self.showFid()
def resetExtraLocList(self, num=None):
+ """
+ Resets the location list (active slice) of all extra data or
+ a specific data set.
+
+ Parameters
+ ----------
+ num (optional = None): int
+ Index of the data to be adjusted. If None, reset all.
+ """
if num is None:
for i in range(len(self.viewSettings["extraLoc"])):
self.viewSettings["extraLoc"][i] = [0] * (len(self.viewSettings["extraData"][i].shape()))
else:
self.viewSettings["extraLoc"][num] = [0] * (len(self.viewSettings["extraData"][num].shape()))
- def showFid(self, oldData=None, extraX=None, extraY=None, extraColor=None): # display the 1D data
+ def showFid(self, oldData=None, extraX=None, extraY=None, extraColor=None):
+ """
+ Plot all data.
+
+ Parameters
+ ----------
+ oldData (optional = None): hypercomplex data type
+ The old data, to display under the current (i.e. during apodization).
+ extraX (optional = None): list of ndarrays
+ List of extra x-axes for 1D data curves
+ extray (optional = None): list of ndarrays
+ List of extra intensity data for 1D data curves
+ extraColor (optional = None): list of color strings
+ List of color strings for the extra data
+ """
self.peakPickReset()
tmpdata = self.data1D.getHyperData(0)
self.ax.cla()
@@ -1268,8 +2722,8 @@ def showFid(self, oldData=None, extraX=None, extraY=None, extraColor=None): # d
self.line_xdata_extra.append(self.xax() * axMult)
self.line_ydata_extra.append(tmp)
self.ax.plot(self.line_xdata_extra[-1], self.line_ydata_extra[-1], marker=marker, linestyle=linestyle, c='k', alpha=0.2, linewidth=self.viewSettings["linewidth"], label=self.data.name + '_old', picker=True)
- if (extraX is not None):
- for num in range(len(extraX)):
+ if extraX is not None:
+ for num, _ in enumerate(extraX):
self.line_xdata_extra.append(extraX[num] * axMult)
self.line_ydata_extra.append(extraY[num])
if extraColor is None:
@@ -1281,7 +2735,7 @@ def showFid(self, oldData=None, extraX=None, extraY=None, extraColor=None): # d
color = extraColor[num]
self.ax.plot(self.line_xdata_extra[-1], self.line_ydata_extra[-1], marker=marker, linestyle=linestyle, linewidth=self.viewSettings["linewidth"], c=color, picker=True)
tmpdata = self.getDataType(tmpdata)
- if(self.viewSettings["plotType"] == 2):
+ if self.viewSettings["plotType"] == 2:
self.line_xdata.append(self.line_xdata[-1])
self.line_ydata = [np.imag(tmpdata), np.real(tmpdata)]
self.ax.plot(self.line_xdata[-2], self.line_ydata[-2], marker=marker, linestyle=linestyle, c='#FF7F0E', linewidth=self.viewSettings["linewidth"], label=self.data.name + '_imag', picker=True)
@@ -1300,7 +2754,7 @@ def showFid(self, oldData=None, extraX=None, extraY=None, extraColor=None): # d
self.ax.set_xlim(self.xminlim, self.xmaxlim)
self.ax.set_ylim(self.yminlim, self.ymaxlim)
self.canvas.draw()
-
+
#########################################################################################################
# the class from which the stacked data is displayed, the operations which only edit the content of this class are for previewing
@@ -1313,18 +2767,51 @@ class CurrentStacked(Current1D):
NDIM_PLOT = 2
def startUp(self, xReset=True, yReset=True):
+ """
+ Run when starting this plot.
+
+ Parameters
+ ----------
+ xReset (optional = True): boolean
+ Reset the x-axis if True
+
+ yReset (optional = True): boolean
+ Reset the y-axis if True
+ """
self.resetSpacing()
self.showFid()
self.plotReset(xReset, yReset)
def copyCurrent(self, root, fig, canvas, data):
+ """
+ Make a copy of the current data structure and the
+ associated canvas and axis information.
+
+ Parameters
+ ----------
+ root: main1Dwindow
+ The basic window
+ fig: matplotib figure
+ The figure
+ canvas: matplotlib canvas
+ The plot canvas
+ data: spectrum class instance
+ The data class
+
+ Returns
+ -------
+ CurrentStacked view class
+ """
return CurrentStacked(root, fig, canvas, data, self)
- def upd(self): # get new data from the data instance
+ def upd(self):
+ """
+ Get new data from the data instance
+ """
if self.data.ndim() < 2:
self.root.rescue()
return False
- if self.data.ndim() <= self.axes[-1] or self.data.ndim() <= self.axes[-2] or self.axes[-1]==self.axes[-2]:
+ if self.data.ndim() <= self.axes[-1] or self.data.ndim() <= self.axes[-2] or self.axes[-1] == self.axes[-2]:
self.axes = np.array([len(self.data.shape()) - 2, len(self.data.shape()) - 1])
if len(self.locList) != self.data.ndim():
self.resetLocList()
@@ -1343,6 +2830,20 @@ def upd(self): # get new data from the data instance
return True
def stackSelect(self, stackBegin, stackEnd, stackStep):
+ """
+ Select which data to plot in the stack plot.
+ The data indexes go from stackBegin to stackEnd with stackStep as
+ step size.
+
+ Parameters
+ ----------
+ stackBegin: int
+ Bgin value of the series
+ stackEnd: int
+ End value of the series. Note that in python, this value is not inluded (0:2 gives 0,1)
+ stackStep: int
+ Step size
+ """
self.viewSettings["stackBegin"] = stackBegin
self.viewSettings["stackEnd"] = stackEnd
self.viewSettings["stackStep"] = stackStep
@@ -1351,11 +2852,27 @@ def stackSelect(self, stackBegin, stackEnd, stackStep):
self.plotReset(self.X_RESIZE, self.Y_RESIZE)
def setSpacing(self, spacing):
+ """
+ Sets the vertical spacing between the different traces.
+
+ Parameters
+ ----------
+ spacing: float
+ The new spacing
+ """
self.viewSettings["spacing"] = spacing
self.showFid()
self.plotReset(self.X_RESIZE, self.Y_RESIZE)
- def resetSpacing(self):
+ def resetSpacing(self, zlims=True):
+ """
+ Reset plot spacing
+
+ Parameters
+ ----------
+ zlims:
+ Not used
+ """
difference = np.diff(self.data1D.getHyperData(0), axis=0)
if difference.size == 0:
self.viewSettings["spacing"] = 0
@@ -1367,16 +2884,40 @@ def resetSpacing(self):
self.viewSettings["spacing"] = np.abs(difference) + 0.1 * amp
def altScroll(self, event):
+ """
+ Scroll spacing
+
+ Parameters
+ ----------
+ event: mouse event
+ """
self.viewSettings["spacing"] = self.viewSettings["spacing"] * 1.1**event.step
self.root.sideframe.scrollSpacing(self.viewSettings["spacing"])
self.showFid()
def altReset(self):
+ """
+ Reset the spacing.
+ """
self.resetSpacing()
self.root.sideframe.scrollSpacing(self.viewSettings["spacing"])
self.showFid()
- def showFid(self, oldData=None, extraX=None, extraY=None, extraColor=None): # display the 1D data
+ def showFid(self, oldData=None, extraX=None, extraY=None, extraColor=None):
+ """
+ Plot the data.
+
+ Parameters
+ ----------
+ oldData (optional = None): hypercomplex data type
+ The old data, to display under the current (i.e. during apodization).
+ extraX (optional = None): list of ndarrays
+ List of extra x-axes for 1D data curves
+ extray (optional = None): list of ndarrays
+ List of extra intensity data for 1D data curves
+ extraColor (optional = None): list of color strings
+ List of color strings for the extra data
+ """
self.peakPickReset()
tmpdata = self.data1D.getHyperData(0)
self.ax.cla()
@@ -1398,9 +2939,9 @@ def showFid(self, oldData=None, extraX=None, extraY=None, extraColor=None): # d
self.line_xdata_extra.append(tmp_line_xdata)
self.line_ydata_extra.append(num * self.viewSettings["spacing"] + tmp)
self.ax.plot(self.line_xdata_extra[-1], self.line_ydata_extra[-1], marker=marker, linestyle=linestyle, c='k', alpha=0.2, linewidth=self.viewSettings["linewidth"], label=self.data.name + '_old', picker=True)
- if (extraX is not None):
+ if extraX is not None:
tmpx = extraX[0] * axMult
- for num in range(len(extraY)):
+ for num, _ in enumerate(extraY):
self.line_xdata_extra.append(tmpx)
self.line_ydata_extra.append(num * self.viewSettings["spacing"] + extraY[num])
if extraColor is None:
@@ -1416,8 +2957,8 @@ def showFid(self, oldData=None, extraX=None, extraY=None, extraColor=None): # d
colorRange = None
else:
colorRange = get_cmap(self.viewSettings["colorRange"])
- for num in range(len(tmpdata)):
- if (self.viewSettings["plotType"] == 2):
+ for num, _ in enumerate(tmpdata):
+ if self.viewSettings["plotType"] == 2:
self.line_xdata.append(tmp_line_xdata)
self.line_ydata.append(num * self.viewSettings["spacing"] + np.imag(tmpdata[num]))
self.ax.plot(self.line_xdata[-1], self.line_ydata[-1], marker=marker, linestyle=linestyle, c='#FF7F0E', linewidth=self.viewSettings["linewidth"], label=self.data.name + '_imag', picker=True)
@@ -1468,31 +3009,107 @@ def __init__(self, root, fig, canvas, data, duplicateCurrent=None):
super(CurrentArrayed, self).__init__(root, fig, canvas, data, duplicateCurrent)
def startUp(self, xReset=True, yReset=True):
+ """
+ Run when starting this plot.
+
+ Parameters
+ ----------
+ xReset (optional = True): boolean
+ Reset the x-axis if True
+
+ yReset (optional = True): boolean
+ Reset the y-axis if True
+ """
self.resetSpacing(False)
self.showFid()
self.plotReset(xReset, yReset)
def copyCurrent(self, root, fig, canvas, data):
+ """
+ Make a copy of the current data structure and the
+ associated canvas and axis information.
+
+ Parameters
+ ----------
+ root: main1Dwindow
+ The basic window
+ fig: matplotib figure
+ The figure
+ canvas: matplotlib canvas
+ The plot canvas
+ data: spectrum class instance
+ The data class
+
+ Returns
+ -------
+ CurrentArrayed view class
+ """
return CurrentArrayed(root, fig, canvas, data, self)
def setAxType(self, val, update=True, num=-1):
#Reimplement of base function. Prevent change of yaxis limits
- yminlimBack = self.yminlim
- ymaxlimBack = self.ymaxlim
+ """
+ Change the axis type if the x-axis.
+
+ The type can be 0,1,2 or 3.
+ For a spectrum axis:
+ 0: Hz
+ 1: kHz
+ 2: MHz
+ 3: ppm
+
+ For an FID axis:
+ 0: s
+ 1: ms
+ 2: us
+
+ Parameters
+ ----------
+ val: int
+ The new axis type
+ update (optional = True): boolean
+ If True, update the displays with the new axis.
+ num (optional = -1): int
+ Which axis to change (default -1 is the x-axis, -2 would be the y axis, etc.)
+ """
+ yminlimBack = self.yminlim
+ ymaxlimBack = self.ymaxlim
super(CurrentArrayed, self).setAxType(val, False, num)
- self.yminlim = yminlimBack
- self.ymaxlim = ymaxlimBack
+ self.yminlim = yminlimBack
+ self.ymaxlim = ymaxlimBack
if update:
self.showFid()
def resetSpacing(self, zlims=True):
+ """
+ Reset spacing
+
+ Parameters
+ ----------
+ zlims (optional = True): boolean
+ If True, reset the limits of the individual x-axes too.
+ """
if zlims:
self.zminlim = min(self.xax())
self.zmaxlim = max(self.xax())
xaxZlims = (self.xax() > self.zminlim) & (self.xax() < self.zmaxlim)
self.viewSettings["spacing"] = (self.xax()[xaxZlims][-1] - self.xax()[xaxZlims][0]) * 1.1
- def showFid(self, oldData=None, extraX=None, extraY=None, extraColor=None): # display the 1D data
+ def showFid(self, oldData=None, extraX=None, extraY=None, extraColor=None):
+ """
+ Plot the data.
+
+ Parameters
+ ----------
+ oldData (optional = None): hypercomplex data type
+ The old data, to display under the current (i.e. during apodization).
+ extraX (optional = None): list of ndarrays
+ List of extra x-axes for 1D data curves
+ extray (optional = None): list of ndarrays
+ List of extra intensity data for 1D data curves
+ extraColor (optional = None): list of color strings
+ List of color strings for the extra data
+ """
self.peakPickReset()
tmpdata = self.data1D.getHyperData(0)
self.ax.cla()
@@ -1519,9 +3136,9 @@ def showFid(self, oldData=None, extraX=None, extraY=None, extraColor=None): # d
self.line_xdata_extra.append((num * self.viewSettings["spacing"] + self.xax()[xaxZlims]) * axMult)
self.line_ydata_extra.append(tmp[xaxZlims][direc])
self.ax.plot(self.line_xdata_extra[-1], self.line_ydata_extra[-1], marker=marker, linestyle=linestyle, c='k', alpha=0.2, linewidth=self.viewSettings["linewidth"], label=self.data.name + '_old', picker=True)
- if (extraX is not None):
+ if extraX is not None:
extraZlims = (extraX[0] > self.zminlim) & (extraX[0] < self.zmaxlim)
- for num in range(len(extraY)):
+ for num, _ in enumerate(extraY):
self.line_xdata_extra.append((num * self.viewSettings["spacing"] + extraX[0][extraZlims]) * axMult)
self.line_ydata_extra.append(extraY[num][extraZlims][direc])
if extraColor is None:
@@ -1538,8 +3155,8 @@ def showFid(self, oldData=None, extraX=None, extraY=None, extraColor=None): # d
colorRange = None
else:
colorRange = get_cmap(self.viewSettings["colorRange"])
- for num in range(len(tmpdata)):
- if (self.viewSettings["plotType"] == 2):
+ for num, _ in enumerate(tmpdata):
+ if self.viewSettings["plotType"] == 2:
self.line_xdata.append((num * self.viewSettings["spacing"] + self.xax()[xaxZlims]) * axMult)
self.line_ydata.append(np.imag(tmpdata[num][xaxZlims])[direc])
self.ax.plot(self.line_xdata[-1], self.line_ydata[-1], marker=marker, linestyle=linestyle, c='#FF7F0E', linewidth=self.viewSettings["linewidth"], label=self.data.name + '_imag', picker=True)
@@ -1557,7 +3174,7 @@ def showFid(self, oldData=None, extraX=None, extraY=None, extraColor=None): # d
self.ax.set_xlim(self.xminlim, self.xmaxlim)
self.ax.set_ylim(self.yminlim, self.ymaxlim)
self.ax.get_yaxis().get_major_formatter().set_powerlimits((-4, 4))
- self.setTicks(Xset = False)
+ self.setTicks(Xset=False)
self.ax.xaxis.grid(self.viewSettings["grids"][0])
self.ax.yaxis.grid(self.viewSettings["grids"][1])
self.canvas.draw()
@@ -1566,6 +3183,14 @@ def showFid(self, oldData=None, extraX=None, extraY=None, extraColor=None): # d
def add_diagonal(axes, mult, *line_args, **line_kwargs):
+ """
+ Add a diagonal to the plot.
+
+ Parameters
+ ----------
+ axes: matplotlib axes
+ mult: diagonal multiplier (1 is true diagonal).
+ """
identity, = axes.plot([], [], *line_args, **line_kwargs)
def callback(axes):
@@ -1596,12 +3221,30 @@ class CurrentContour(CurrentStacked):
GRID_PLOT = True
INVERT_Y = True
ZERO_SCROLL_ALLOWED = False
-
+
def startUp(self, xReset=True, yReset=True):
+ """
+ Run when starting this plot.
+
+ Parameters
+ ----------
+ xReset (optional = True): boolean
+ Reset the x-axis if True
+
+ yReset (optional = True): boolean
+ Reset the y-axis if True
+ """
self.showFid()
self.plotReset(xReset, yReset)
-
- def altScroll(self, event): # Shift scroll scrolls contour limits
+
+ def altScroll(self, event):
+ """
+ Scroll contour level limit.
+
+ Parameters
+ ----------
+ event: mouse event
+ """
minLevels = self.viewSettings["minLevels"] / 1.1**event.step
if minLevels > 1:
minLevels = 1
@@ -1613,9 +3256,48 @@ def altScroll(self, event): # Shift scroll scrolls contour limits
self.showFid()
def copyCurrent(self, root, fig, canvas, data):
+ """
+ Make a copy of the current data structure and the
+ associated canvas and axis information.
+
+ Parameters
+ ----------
+ root: main1Dwindow
+ The basic window
+ fig: matplotib figure
+ The figure
+ canvas: matplotlib canvas
+ The plot canvas
+ data: spectrum class instance
+ The data class
+
+ Returns
+ -------
+ CurrenContour view class
+ """
return CurrentContour(root, fig, canvas, data, self)
def setLevels(self, numLevels, maxLevels, minLevels, limitType, contourSign, contourType, multiValue):
+ """
+ Sets the contour settings
+
+ Parameters
+ ----------
+ numLevels: int
+ Number of contours
+ maxLevels: float
+ Maximum value (1 is max) of the contours
+ minLevels: float
+ Minimum level of the contours
+ limitType: int
+ 0: relative to current 2D slice 1: relative to full data
+ contourSign: int
+ 0: both, 1: + only 2: - only
+ contourType: int
+ 0: linear 1: multiplier
+ multiValue: float
+ Value of the multiplier
+ """
self.viewSettings["numLevels"] = numLevels
self.viewSettings["maxLevels"] = maxLevels
self.viewSettings["minLevels"] = minLevels
@@ -1626,23 +3308,76 @@ def setLevels(self, numLevels, maxLevels, minLevels, limitType, contourSign, con
self.showFid()
def setProjLimits(self, ProjBool, Limits):
+ """
+ Set projection limits (i.e. ranges).
+
+ Parameters
+ ----------
+ ProjBool: boolean
+ If True, projection ranges are taken into account.
+ Limits: list of 4 ints
+ Slice positions that limit the projections
+ """
self.viewSettings["projLimits"] = Limits
self.viewSettings["projLimitsBool"] = ProjBool
def setProjPos(self, pos):
+ """
+ Sets the projection slice, if a specific slice is plot as the projection.
+
+ Parameters
+ ----------
+ pos: list of ints
+ The slices to be taken
+ """
self.viewSettings["projPos"] = pos
def setProjType(self, val, direc):
+ """
+ Set the type of projection
+
+ Parameters
+ ----------
+ val: int
+ The type. 0: sum 1: max 2: min 3: off 4: slice 5: diagonal
+ direct: int
+ 1: top 2: right
+ """
if direc == 1:
self.viewSettings["projTop"] = val
if direc == 2:
self.viewSettings["projRight"] = val
def setProjTraces(self, val, direc):
+ """
+ Set a specific trace for a projection.
+
+ Parameters
+ ----------
+ val: int
+ The trace index
+ direct: int
+ 1: top 2: right
+ """
self.viewSettings["projPos"][direc] = val
def integralsPreview(self, xMin, xMax, yMin, yMax):
- nPatches = min(len(xMin),len(xMax),len(yMin),len(yMax))
+ """
+ Draw different rectanglur patches, for a preview of
+ the intergral selection tool.
+
+ Parameters
+ ----------
+ xMin: list of int
+ Minimum x positions of the rectangles
+ xMax: list of int
+ Maximum x positions of the rectangles
+ yMin: list of int
+ Minimum y positions of the rectangles
+ yMax: list of int
+ Maximum y positions of the rectangles
+ """
+ nPatches = min(len(xMin), len(xMax), len(yMin), len(yMax))
self.resetPreviewRemoveList()
xax = self.xax()
yax = self.xax(-2)
@@ -1654,41 +3389,60 @@ def integralsPreview(self, xMin, xMax, yMin, yMax):
xmaxTmp = xax[xMax[i]] * xaxMult
yminTmp = yax[yMin[i]] * yaxMult
ymaxTmp = yax[yMax[i]] * yaxMult
- self.removeListLines.append(self.ax.fill([xminTmp,xminTmp,xmaxTmp,xmaxTmp],[yminTmp,ymaxTmp,ymaxTmp,yminTmp],color=color,fill = False, linestyle='--')[0])
+ self.removeListLines.append(self.ax.fill([xminTmp, xminTmp, xmaxTmp, xmaxTmp], [yminTmp, ymaxTmp, ymaxTmp, yminTmp],color=color, fill=False, linestyle='--')[0])
self.canvas.draw()
- def updateAxes(self, oldAx, newAx, axis):
- scale = newAx / oldAx
- # Scale the path vertices, so no new contours need to be calculated
- cols = self.ax.collections
- for col in cols:
- paths = col.get_paths()
- for path in paths:
- tmp = path.vertices
- tmp[:,axis] = tmp[:,axis] * scale
- path.vertices = tmp
- # Scale the projections
- if axis == 1: # Yaxis
- line = self.y_ax.lines
- line[0].set_ydata(line[0].get_ydata() * scale)
- else:
- line = self.x_ax.lines
- line[0].set_xdata(line[0].get_xdata() * scale)
- # Set the labels
- self.ax.set_xlabel(self.getLabel(self.spec(), self.axes[-1], self.getAxType(), self.getppm()))
- self.ax.set_ylabel(self.getLabel(self.spec(-2), self.axes[-2], self.getAxType(-2), self.getppm(-2)))
- # Set the zoom
- if axis == 1:
- ylim = self.ax.get_ylim()
- self.ax.set_ylim(ylim[0] * scale, ylim[1] * scale)
- self.line_ydata = [item*scale for item in self.line_ydata]
- else:
- xlim = self.ax.get_xlim()
- self.ax.set_xlim(xlim[0] * scale, xlim[1] * scale)
- self.line_xdata = [item*scale for item in self.line_xdata]
- self.canvas.draw()
+ #def updateAxes(self, oldAx, newAx, axis):
+ # """
+ # Update the axis without recalculating the contours.
+ # """
+ # scale = newAx / oldAx
+ # # Scale the path vertices, so no new contours need to be calculated
+ # cols = self.ax.collections
+ # for col in cols:
+ # paths = col.get_paths()
+ # for path in paths:
+ # tmp = path.vertices
+ # tmp[:, axis] = tmp[:, axis] * scale
+ # path.vertices = tmp
+ # # Scale the projections
+ # if axis == 1: # Yaxis
+ # line = self.y_ax.lines
+ # line[0].set_ydata(line[0].get_ydata() * scale)
+ # else:
+ # line = self.x_ax.lines
+ # line[0].set_xdata(line[0].get_xdata() * scale)
+ # # Set the labels
+ # self.ax.set_xlabel(self.getLabel(self.spec(), self.axes[-1], self.getAxType(), self.getppm()))
+ # self.ax.set_ylabel(self.getLabel(self.spec(-2), self.axes[-2], self.getAxType(-2), self.getppm(-2)))
+ # # Set the zoom
+ # if axis == 1:
+ # ylim = self.ax.get_ylim()
+ # self.ax.set_ylim(ylim[0] * scale, ylim[1] * scale)
+ # self.line_ydata = [item*scale for item in self.line_ydata]
+ # else:
+ # xlim = self.ax.get_xlim()
+ # self.ax.set_xlim(xlim[0] * scale, xlim[1] * scale)
+ # self.line_xdata = [item*scale for item in self.line_xdata]
+ # self.canvas.draw()
def showFid(self, oldData=None, extraX=None, extraY=None, extraZ=None, extraColor=None):
+ """
+ Plot the data.
+
+ Parameters
+ ----------
+ oldData (optional = None): hypercomplex data type
+ The old data, to display under the current (i.e. during apodization).
+ extraX (optional = None): list of ndarrays
+ List of extra x-axes for data curves
+ extraY (optional = None): list of ndarrays
+ List of extra y-axes for data curves
+ extraZ (optional = None): list of ndarrays
+ List of extra intensity data for 1D data curves
+ extraColor (optional = None): list of color strings
+ List of color strings for the extra data
+ """
# The oldData and extra plots are not displayed in the contourplot for now
self.line_xdata_extra = []
self.line_ydata_extra = []
@@ -1711,10 +3465,10 @@ def showFid(self, oldData=None, extraX=None, extraY=None, extraZ=None, extraColo
self.line_xdata_extra.append(self.xax() * axMult)
self.line_ydata_extra.append(self.xax(-2) * axMult2)
self.line_zdata_extra.append(tmp)
- self.plotContour(self.line_xdata_extra[-1], self.line_ydata_extra[-1], self.line_zdata_extra[-1], color=['k','k'], alpha=0.2)
+ self.plotContour(self.line_xdata_extra[-1], self.line_ydata_extra[-1], self.line_zdata_extra[-1], color=['k', 'k'], alpha=0.2)
self.showProj(self.line_xdata_extra[-1], self.line_ydata_extra[-1], self.line_zdata_extra[-1], 'k')
if extraX is not None:
- for num in range(len(extraX)):
+ for num, _ in enumerate(extraX):
self.line_xdata_extra.append(extraX[num] * axMult)
self.line_ydata_extra.append(extraY[num] * axMult2)
self.line_zdata_extra.append(extraZ[num])
@@ -1752,7 +3506,25 @@ def showFid(self, oldData=None, extraX=None, extraY=None, extraZ=None, extraColo
self.setTicks()
self.canvas.draw()
- def plotContour(self, line_xdata, line_ydata, line_zdata, color=None, alpha=1, updateOnly=False): # Plots the contour plot
+ def plotContour(self, line_xdata, line_ydata, line_zdata, color=None, alpha=1, updateOnly=False):
+ """
+ Make the contour plot
+
+ Parameters
+ ----------
+ line_xdata: 1darray
+ xaxis
+ line_ydata: 1darray
+ yaxis
+ line_zdata: 2darray
+ Intensity (z) data
+ color (optional = None): list of colors
+ If not None, positive and negative contour colors should be in here
+ alpha (optional = 1): float
+ Opacity of the lines (1 is solid)
+ updateOnly (optional = False): booleans
+ If True, update only the contour plot
+ """
if color is None and self.viewSettings["contourConst"]:
color = self.viewSettings["contourColors"]
X, Y = np.meshgrid(line_xdata, line_ydata)
@@ -1780,7 +3552,7 @@ def plotContour(self, line_xdata, line_ydata, line_zdata, color=None, alpha=1, u
PlotPositive = True
PlotNegative = False
if self.viewSettings["contourSign"] == 0 or self.viewSettings["contourSign"] == 2:
- if not self.viewSettings["plotType"] == 3: # for Absolute plot no negative
+ if self.viewSettings["plotType"] != 3: # for Absolute plot no negative
if line_zdata.shape[0] > 2:
YposMin = np.where(np.convolve(np.min(line_zdata, 1) < -contourLevels[0], [True, True, True], 'same'))[0]
else:
@@ -1795,23 +3567,41 @@ def plotContour(self, line_xdata, line_ydata, line_zdata, color=None, alpha=1, u
vmin = -vmax
if color is not None:
if PlotPositive:
- self.ax.contour(X[YposMax[:,None],XposMax],Y[YposMax[:,None],XposMax],line_zdata[YposMax[:,None],XposMax], colors=color[0], alpha=alpha, levels=contourLevels, vmax=vmax, vmin=vmin, linewidths=self.viewSettings["linewidth"], linestyles='solid')
+ self.ax.contour(X[YposMax[:, None], XposMax], Y[YposMax[:, None], XposMax], line_zdata[YposMax[:, None], XposMax], colors=color[0], alpha=alpha, levels=contourLevels, vmax=vmax, vmin=vmin, linewidths=self.viewSettings["linewidth"], linestyles='solid')
if PlotNegative:
- self.ax.contour(X[YposMin[:,None],XposMin],Y[YposMin[:,None],XposMin],line_zdata[YposMin[:,None],XposMin], colors=color[1], alpha=alpha, levels=-contourLevels[::-1], vmax=vmax, vmin=vmin, linewidths=self.viewSettings["linewidth"], linestyles='solid')
+ self.ax.contour(X[YposMin[:, None], XposMin], Y[YposMin[:, None], XposMin], line_zdata[YposMin[:, None], XposMin], colors=color[1], alpha=alpha, levels=-contourLevels[::-1], vmax=vmax, vmin=vmin, linewidths=self.viewSettings["linewidth"], linestyles='solid')
else:
if PlotPositive:
- self.ax.contour(X[YposMax[:,None],XposMax],Y[YposMax[:,None],XposMax],line_zdata[YposMax[:,None],XposMax], cmap=get_cmap(self.viewSettings["colorMap"]), levels=contourLevels, vmax=vmax, vmin=vmin, linewidths=self.viewSettings["linewidth"], linestyles='solid')
- if PlotNegative:
- self.ax.contour(X[YposMin[:,None],XposMin],Y[YposMin[:,None],XposMin],line_zdata[YposMin[:,None],XposMin], cmap=get_cmap(self.viewSettings["colorMap"]), levels=-contourLevels[::-1], vmax=vmax, vmin=vmin, linewidths=self.viewSettings["linewidth"], linestyles='solid')
+ self.ax.contour(X[YposMax[:, None], XposMax], Y[YposMax[:, None], XposMax], line_zdata[YposMax[:, None], XposMax], cmap=get_cmap(self.viewSettings["colorMap"]), levels=contourLevels, vmax=vmax, vmin=vmin, linewidths=self.viewSettings["linewidth"], linestyles='solid')
+ if PlotNegative:
+ self.ax.contour(X[YposMin[:, None], XposMin], Y[YposMin[:, None], XposMin], line_zdata[YposMin[:, None], XposMin], cmap=get_cmap(self.viewSettings["colorMap"]), levels=-contourLevels[::-1], vmax=vmax, vmin=vmin, linewidths=self.viewSettings["linewidth"], linestyles='solid')
self.setTicks()
if updateOnly:
self.canvas.draw()
def clearProj(self):
+ """
+ Clear the projections.
+ """
self.x_ax.cla()
self.y_ax.cla()
def showProj(self, line_xdata=None, line_ydata=None, line_zdata=None, color=None):
+ """
+ Show the projections
+
+
+ Parameters
+ ----------
+ line_xdata (optional = None): 1darray
+ xaxis
+ line_ydata (optional = None): 1darray
+ yaxis
+ line_zdata (optional = None): 2darray
+ Intensity (z) data
+ color (optional = None): color string
+ Colour of the projection lines
+ """
xLimOld = self.x_ax.get_xlim()
if line_xdata is None:
x = self.line_xdata[-1]
@@ -1861,11 +3651,11 @@ def showProj(self, line_xdata=None, line_ydata=None, line_zdata=None, color=None
dist2 = y[indices2] - x
distSum = (dist1 + dist2)
xprojdata = dist2 * tmpdata[indices1, np.arange(len(x))] + dist1 * tmpdata[indices2, np.arange(len(x))]
- xprojdata[distSum!=0.0] /= distSum[distSum!=0.0]
+ xprojdata[distSum != 0.0] /= distSum[distSum != 0.0]
xprojdata[x > np.max(y)] = np.nan
xprojdata[x < np.min(y)] = np.nan
if self.viewSettings["projTop"] != 3:
- self.x_ax.plot(x, xprojdata, color=color, linewidth=self.viewSettings["linewidth"], picker=True)
+ self.x_ax.plot(x, xprojdata, color=color, linewidth=self.viewSettings["linewidth"], picker=True)
xmin, xmax = np.nanmin(xprojdata), np.nanmax(xprojdata)
self.x_ax.set_ylim([xmin - 0.15 * (xmax - xmin), xmax + 0.05 * (xmax - xmin)]) # Set projection limits, and force 15% whitespace below plot
self.x_ax.set_xlim(xLimOld)
@@ -1890,7 +3680,7 @@ def showProj(self, line_xdata=None, line_ydata=None, line_zdata=None, color=None
dist2 = x[indices2] - y
distSum = (dist1 + dist2)
yprojdata = dist2 * tmpdata[np.arange(len(y)), indices1] + dist1 * tmpdata[np.arange(len(y)), indices2]
- yprojdata[distSum!=0.0] /= distSum[distSum!=0.0]
+ yprojdata[distSum != 0.0] /= distSum[distSum != 0.0]
yprojdata[y > np.max(x)] = np.nan
yprojdata[y < np.min(x)] = np.nan
if self.viewSettings["projRight"] != 3:
@@ -1953,3 +3743,42 @@ def buttonRelease(self, event):
self.rightMouse = False
self.canvas.draw()
+
+
+class CurrentColour2D(CurrentContour):
+ """
+ 2D colour plot class. Currently a child of CurrentContour. Probably a lower level 2D class
+ should be made.
+ """
+
+ X_RESIZE = False
+ Y_RESIZE = True
+ GRID_PLOT = True
+ INVERT_Y = True
+ ZERO_SCROLL_ALLOWED = False
+ def plotContour(self, line_xdata, line_ydata, line_zdata, color=None, alpha=1, updateOnly=False):
+ """
+ Make the contour plot
+
+ Parameters
+ ----------
+ line_xdata: 1darray
+ xaxis
+ line_ydata: 1darray
+ yaxis
+ line_zdata: 2darray
+ Intensity (z) data
+ color (optional = None): list of colors
+ If not None, positive and negative contour colors should be in here
+ alpha (optional = 1): float
+ Opacity of the lines (1 is solid)
+ updateOnly (optional = False): booleans
+ If True, update only the contour plot
+ """
+ if updateOnly: # Set some extra stuff if only the contour plot needs updating
+ del self.ax.collections[:] # Clear all plot collections
+
+ self.ax.imshow(np.flipud(line_zdata),extent = [line_xdata[0],line_xdata[-1],line_ydata[0],line_ydata[-1]],aspect='auto')
+ self.setTicks()
+ if updateOnly:
+ self.canvas.draw()
diff --git a/src/widgetClasses.py b/src/widgetClasses.py
index 33622f0a..220be51a 100644
--- a/src/widgetClasses.py
+++ b/src/widgetClasses.py
@@ -17,21 +17,47 @@
# You should have received a copy of the GNU General Public License
# along with ssNake. If not, see .
-from safeEval import safeEval
import os
+import sys
+from safeEval import safeEval
from ssNake import QtGui, QtCore, QtWidgets, QT
class SsnakeTabs(QtWidgets.QTabWidget):
- # A tab widget were tabs can be closed with the middle mouse button
+ """
+ A reimplementation of the PyQt QTabWidget.
+ A tab widget were tabs can be closed with the middle mouse button.
+ """
def mousePressEvent(self, event):
+ """
+ Reimplementation from QTabWidget.
+ Middle mousebutton closes the tab.
+
+ Parameters
+ ----------
+ event : QMouseEvent
+ The mouse event.
+ """
if event.button() == QtCore.Qt.MidButton:
index = self.tabBar().tabAt(event.pos())
if index >= 0:
self.tabCloseRequested.emit(index)
class SsnakeTreeWidget(QtWidgets.QTreeView):
- def __init__(self, parent, startDir=None):
+ """
+ A reimplementation of the PyQt QTreeView.
+ Allows the loading of files and directories in ssNake.
+ """
+
+ def __init__(self, parent):
+ """
+ Initializes the SsnakeTreeWidget.
+
+ Parameters
+ ----------
+ parent : QWidget
+ Parent of the treeview.
+ """
super(SsnakeTreeWidget, self).__init__(parent)
self.father = parent
self.dirmodel = QtWidgets.QFileSystemModel()
@@ -56,26 +82,52 @@ def __init__(self, parent, startDir=None):
self.hideColumn(3)
self.expand_all(self.dirmodel.index(self.father.lastLocation))
- def mouseDoubleClickEvent(self,event):
+ def mouseDoubleClickEvent(self, event):
+ """
+ Reimplementation from QTreeView.
+ Middle mousebutton loads the data.
+ Left mousebutton loads the data from a file.
+
+ Parameters
+ ----------
+ event : QMouseEvent
+ The mouse event.
+ """
index = self.indexAt(event.pos())
- path = self.dirmodel.filePath(index)
+ path = self.dirmodel.filePath(index)
if event.button() == QtCore.Qt.MidButton:
- self.loadAct([path])
+ self.father.loadData([path])
elif event.button() == QtCore.Qt.LeftButton and not self.dirmodel.isDir(index):
- self.loadAct([path])
+ self.father.loadData([path])
super(SsnakeTreeWidget, self).mouseDoubleClickEvent(event)
- def mousePressEvent(self,event):
+ def mousePressEvent(self, event):
+ """
+ Reimplementation from QTreeView.
+ Middle mousebutton loads the data.
+
+ Parameters
+ ----------
+ event : QMouseEvent
+ The mouse event.
+ """
if event.button() == QtCore.Qt.MidButton:
index = self.indexAt(event.pos())
- path = self.dirmodel.filePath(index)
- self.loadAct([path])
+ path = self.dirmodel.filePath(index)
+ self.father.loadData([path])
else: #If not, let the QTreeView handle the event
super(SsnakeTreeWidget, self).mousePressEvent(event)
def expand_all(self, index):
- path = self.dirmodel.filePath(index)
- run = True
+ """
+ Expand all folders up to a certain index.
+
+ Parameters
+ ----------
+ event : QModelIndex
+ The index to which the folder should be expanded in the treeview.
+ """
+ path = self.dirmodel.filePath(index)
pathOld = '-1'
while pathOld != path:
self.setExpanded(self.dirmodel.index(path), True)
@@ -83,23 +135,83 @@ def expand_all(self, index):
path = os.path.dirname(path)
def openMenu(self, position):
+ """
+ Creates the contextmenu of the treeview at a given position.
+ The contents of the contextmenu depend on whether the selected item is a file or a directory.
+
+ Parameters
+ ----------
+ position : QPoint
+ The position to place the contextmenu.
+ """
index = self.selectedIndexes()
path = [self.dirmodel.filePath(x) for x in index]
menu = QtWidgets.QMenu()
if len(path) == 1:
if self.dirmodel.isDir(index[0]):
- menu.addAction("Load Directory", lambda: self.loadAct(path))
+ menu.addAction("Load Directory", lambda: self.father.loadData(path))
else:
- menu.addAction("Load File", lambda: self.loadAct(path))
+ menu.addAction("Load File", lambda: self.father.loadData(path))
+ menu.addAction("Open File Externally", lambda: self.openExtAct(path))
+ menu.addAction("Open in File Browser", lambda: self.openBrowser(path))
else:
- menu.addAction("Load Selection", lambda: self.loadAct(path))
+ menu.addAction("Load Selection", lambda: self.father.loadData(path))
menu.exec_(self.viewport().mapToGlobal(position))
- def loadAct(self,path):
- self.father.loadData(path)
-
+ def openExtAct(self, fileNames):
+ """
+ Opens a file externally.
+
+ Parameters
+ ----------
+ fileNames : list of str
+ The first string from the list is used as a path to open externally.
+ """
+ fileName = fileNames[0]
+ if sys.platform.startswith('linux'):
+ os.system("xdg-open " + '"' + fileName + '"')
+ elif sys.platform.startswith('darwin'):
+ os.system("open " + '"' + fileName + '"')
+ elif sys.platform.startswith('win'):
+ os.startfile(fileName)
+
+ def openBrowser(self, path):
+ """
+ Opens a directory using the filebrowser.
+ When the a file is given the containing directory is used.
+
+ Parameters
+ ----------
+ path : list of str
+ The first string from the list is used as the path to open in a filebrowser.
+ """
+ path = os.path.dirname(path[0])
+ if sys.platform.startswith('linux'):
+ os.system("xdg-open " + '"' + path + '"')
+ elif sys.platform.startswith('darwin'):
+ os.system("open " + '"' + path + '"')
+ elif sys.platform.startswith('win'):
+ os.startfile(path)
+
+
class SsnakeSlider(QtWidgets.QSlider):
+ """
+ A reimplementation of the PyQt QSlider.
+ The behaviour is modified when the Control or Shift buttons are pressed.
+ """
+
def wheelEvent(self, event):
+ """
+ Reimplementation from QSlider.
+ When the Control button is held the stepsize is multiplied by 10.
+ When the Shift button is held the stepsize is multiplied by 100.
+ When both Control and Shift buttons are held the stepsize is multiplied by 1000.
+
+ Parameters
+ ----------
+ event : QMouseEvent
+ The mouse event.
+ """
if QT == 4:
delta = event.delta()
else:
@@ -115,24 +227,54 @@ def wheelEvent(self, event):
self.setValue(self.value() + step)
else:
self.setValue(self.value() - step)
-
+
class SplitterEventFilter(QtCore.QObject):
+ """
+ The event filter for the splitter between the treeview and the canvas.
+ """
def __init__(self, root, *args):
+ """
+ Initializes the splitter event filter.
+
+ Parameters
+ ----------
+ root : QSplitter
+ The splitter to which the event filter is installed.
+ *args
+ Additional arguments are passed to QObject.
+ """
super(SplitterEventFilter, self).__init__(*args)
self.root = root
self.sizeBak = 0
def eventFilter(self, receiver, event):
- Select = False
+ """
+ The event filter function.
+ A double mouseclick or a single middle mouseclick minimizes or restores the treeview.
+
+ Parameters
+ ----------
+ receiver : QObject
+ The receiver.
+ Not used.
+ event : QEvent
+ The event.
+
+ Returns
+ -------
+ bool
+ True if the event matched the resize event, False otherwise.
+ """
+ select = False
if event.type() == QtCore.QEvent.MouseButtonDblClick:
- Select = True
- #If single click with middle mouse button
+ select = True
+ # If single click with middle mouse button
if event.type() == QtCore.QEvent.MouseButtonPress:
if event.button() == QtCore.Qt.MidButton:
- Select = True
- if Select:
+ select = True
+ if select:
sizes = self.root.sizes()
if sizes[0] == 0:
self.root.setSizes([self.sizeBak, 1])
@@ -143,37 +285,81 @@ def eventFilter(self, receiver, event):
return False
class SsnakeEventFilter(QtCore.QObject):
+ """
+ The event filter of ssNake for undo and redo.
+ """
def __init__(self, root, *args):
+ """
+ Initializes the ssNake event filter.
+
+ Parameters
+ ----------
+ root : MainProgram
+ The main program to which the event filter is installed.
+ *args
+ Additional arguments are passed to QObject.
+ """
super(SsnakeEventFilter, self).__init__(*args)
self.root = root
def eventFilter(self, receiver, event):
+ """
+ The event filter function.
+ Control + Z triggers the undo function.
+ Control + Shift + Z triggers the redo function.
+
+ Parameters
+ ----------
+ receiver : QObject
+ The receiver.
+ Not used.
+ event : QEvent
+ The event.
+
+ Returns
+ -------
+ bool
+ True if the event matched undo or redo, False otherwise.
+ """
if event.type() == QtCore.QEvent.KeyPress:
if event.key() == QtCore.Qt.Key_Z:
if (event.modifiers() & QtCore.Qt.ControlModifier) and (event.modifiers() & QtCore.Qt.ShiftModifier):
self.root.redo()
return True
- elif event.modifiers() == (QtCore.Qt.ControlModifier):
+ if event.modifiers() == (QtCore.Qt.ControlModifier):
self.root.undo()
return True
return False
-class ToolWindows(QtWidgets.QWidget):
+class ToolWindow(QtWidgets.QWidget):
+ """
+ The base class of the toolwindows.
+ Implements the basic features shared by all toolwindows.
+ Toolwindows inherit this class and alter its behaviour by the constants or by reimplementing functions.
+ """
- NAME = ""
- PICK = False
- SINGLESLICE = False
- BROWSE = False
- RESIZABLE = False
- MENUDISABLE = True
- APPLYANDCLOSE = True
- CANCELNAME = "&Cancel"
- OKNAME = "&Ok"
+ NAME = "" # The name displayed in the title of the window
+ PICK = False # Does the window use peak picking
+ SINGLESLICE = False # Should the single slice button be displayed
+ BROWSE = False # Should the window have a browse button
+ RESIZABLE = False # should the window be resizable
+ MENUDISABLE = True # Should the window disable the menu of the main window
+ APPLYANDCLOSE = True # Should the window close after the ok button is pressed
+ CANCELNAME = "&Cancel" # The name on the cancel button
+ OKNAME = "&Ok" # The name on the ok button
def __init__(self, parent):
- super(ToolWindows, self).__init__(parent)
+ """
+ Initializes the ToolWindow.
+
+ Parameters
+ ----------
+ parent : Main1DWindow or AbstractParamFrame
+ Parent of the toolwindow.
+ """
+ super(ToolWindow, self).__init__(parent)
self.setWindowFlags(QtCore.Qt.Window | QtCore.Qt.Tool)
self.father = parent
self.setWindowTitle(self.NAME)
@@ -196,10 +382,10 @@ def __init__(self, parent):
self.okButton = QtWidgets.QPushButton(self.OKNAME)
self.okButton.clicked.connect(self.applyAndClose)
self.okButton.setFocus()
- self.box.addButton(self.cancelButton,QtWidgets.QDialogButtonBox.RejectRole)
- self.box.addButton(self.okButton,QtWidgets.QDialogButtonBox.AcceptRole)
+ self.box.addButton(self.cancelButton, QtWidgets.QDialogButtonBox.RejectRole)
+ self.box.addButton(self.okButton, QtWidgets.QDialogButtonBox.AcceptRole)
self.show()
- self.layout.addWidget(self.box,3,0)
+ self.layout.addWidget(self.box, 3, 0)
if not self.RESIZABLE:
self.setFixedSize(self.size())
if self.MENUDISABLE:
@@ -207,17 +393,36 @@ def __init__(self, parent):
self.setGeometry(self.frameSize().width() - self.geometry().width(), self.frameSize().height(), 0, 0)
def browse(self):
+ """
+ Dummy function for the Browse button.
+ Should be reimplemented by the toolwindows using BROWSE=True.
+ """
pass
def applyFunc(self):
+ """
+ Dummy function for the apply function.
+ Should be reimplemented by the toolwindows.
+ """
pass
def applyAndClose(self):
+ """
+ Runs the apply function and when APPLYANDCLOSE is set, closes the window.
+ """
self.applyFunc()
if self.APPLYANDCLOSE:
self.closeEvent()
def closeEvent(self, *args):
+ """
+ Updates the view and closes the toolwindow.
+
+ Parameters
+ ----------
+ *args
+ Any arguments are ignored.
+ """
self.father.current.upd()
self.father.current.showFid()
if self.MENUDISABLE:
@@ -227,8 +432,31 @@ def closeEvent(self, *args):
class SliceValidator(QtGui.QValidator):
+ """
+ A reimplementation of the QValidator.
+ It uses the safeEval to validate a string for slice selection.
+ """
def validate(self, string, position):
+ """
+ Validates a given string using safeEval.
+
+ Parameters
+ ----------
+ string : str
+ String to be validated.
+ position : int
+ Position of the cursor.
+
+ Returns
+ -------
+ State
+ Acceptable if the string is parsable by safeEval, Intermediate otherwise.
+ string : str
+ The input string.
+ position : int
+ The input position of the cursor.
+ """
string = str(string)
try:
int(safeEval(string))
@@ -238,42 +466,104 @@ def validate(self, string, position):
class SliceSpinBox(QtWidgets.QSpinBox):
+ """
+ A reimplementation of the QSpinBox.
+ This spinbox is designed for the slice selection of spectra.
+ """
def __init__(self, parent, minimum, maximum, *args, **kwargs):
+ """
+ Initializes the SliceSpinBox.
+
+ Parameters
+ ----------
+ parent : SideFrame
+ The sideframe which contains the SliceSpinBox.
+ minimum : int
+ The minimum value of the spinbox.
+ maximum : int
+ The maximum value of the spinbox.
+ *args
+ Additional arguments are passed to QSpinBox.
+ **kwargs
+ Keyword arguments are passed to QSpinBox
+ """
self.validator = SliceValidator()
+ self.validate = self.validator.validate
+ self.fixup = self.validator.fixup
super(SliceSpinBox, self).__init__(parent, *args, **kwargs)
self.setMinimum(minimum)
self.setMaximum(maximum)
self.setKeyboardTracking(False)
- def validate(self, text, position):
- return self.validator.validate(text, position)
-
- def fixup(self, text):
- return self.validator.fixup(text)
-
def valueFromText(self, text):
+ """
+ Parses a string to a slice number.
+
+ Parameters
+ ----------
+ text : str
+ String to be parsed.
+
+ Returns
+ -------
+ int
+ The slice number.
+ """
inp = int(safeEval(str(text)))
if inp < 0:
inp = inp + self.maximum() + 1
return inp
def textFromValue(self, value):
+ """
+ Parses a value to a slice number.
+
+ Parameters
+ ----------
+ text : int or float
+ Value to be parsed.
+
+ Returns
+ -------
+ int
+ The slice number.
+ """
inp = int(value)
if inp < 0:
inp = inp + self.maximum() + 1
return str(inp)
- def stepBy(self,steps):
+ def stepBy(self, steps):
+ """
+ Increases or decreases the spinbox by a given value.
+ When the Control button is held the stepsize is multiplied 10.
+ When the Shift button is held the stepsize is multiplied 100.
+ When both the Control and Shift buttons are held the stepsize is multiplied 1000.
+
+ Parameters
+ ----------
+ steps : int
+ The number of steps to increase the spinbox
+ """
+ mod = 1
if QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ControlModifier and QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ShiftModifier:
- steps *= 1000
+ mod = 1000
elif QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ControlModifier:
- steps *= 10
+ mod = 10
elif QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ShiftModifier:
- steps *= 100
- self.setValue(self.value() + steps)
+ mod = 100
+ self.setValue(self.value() + mod * steps)
def wheelEvent(self, event):
+ """
+ The function for handling the scroll event on the spinbox.
+
+ Parameters
+ ----------
+ event : QWheelEvent
+ The event on the spinbox.
+ """
if QT == 4:
delta = event.delta()
else:
@@ -285,20 +575,46 @@ def wheelEvent(self, event):
self.stepBy(-step)
event.accept()
+
class SsnakeDoubleSpinBox(QtWidgets.QDoubleSpinBox):
- def stepBy(self,steps):
+ """
+ A reimplementation of the QDoubleSpinBox.
+ """
+
+ def stepBy(self, steps):
+ """
+ Increases or decreases the spinbox by a given value.
+ When the Control button is held the stepsize is multiplied 10.
+ When the Shift button is held the stepsize is multiplied 100.
+ When both the Control and Shift buttons are held the stepsize is multiplied 1000.
+ When the Alt button is held the inverse
+
+ Parameters
+ ----------
+ steps : int or float
+ The value to increase the spinbox
+ """
+ mod = 1
if QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ControlModifier and QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ShiftModifier:
- steps *= 1000
+ mod = 1000
elif QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ControlModifier:
- steps *= 10
+ mod = 10
elif QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ShiftModifier:
- steps *= 100
+ mod = 100
if QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.AltModifier:
- self.setValue(self.value() + self.singleStep() / steps)
+ self.setValue(self.value() + self.singleStep() * steps / mod)
else:
- self.setValue(self.value() + self.singleStep() * steps)
+ self.setValue(self.value() + self.singleStep() * mod * steps)
def wheelEvent(self, event):
+ """
+ The function for handling the scroll event on the spinbox.
+
+ Parameters
+ ----------
+ event : QWheelEvent
+ The event on the spinbox.
+ """
if QT == 4:
delta = event.delta()
else:
@@ -310,17 +626,42 @@ def wheelEvent(self, event):
self.stepBy(-step)
event.accept()
+
class SsnakeSpinBox(QtWidgets.QSpinBox):
- def stepBy(self,steps):
+ """
+ A reimplementation of the QSpinBox.
+ """
+
+ def stepBy(self, steps):
+ """
+ Increases or decreases the spinbox by a given value.
+ When the Control button is held the stepsize is multiplied 10.
+ When the Shift button is held the stepsize is multiplied 100.
+ When both the Control and Shift buttons are held the stepsize is multiplied 1000.
+
+ Parameters
+ ----------
+ steps : int
+ The value to increase the spinbox
+ """
+ mod = 1
if QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ControlModifier and QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ShiftModifier:
- steps *= 1000
+ mod = 1000
elif QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ControlModifier:
- steps *= 10
+ mod = 10
elif QtWidgets.qApp.keyboardModifiers() & QtCore.Qt.ShiftModifier:
- steps *= 100
- self.setValue(self.value() + self.singleStep() * steps)
+ mod = 100
+ self.setValue(self.value() + self.singleStep() * mod * steps)
def wheelEvent(self, event):
+ """
+ The function for handling the scroll event on the spinbox.
+
+ Parameters
+ ----------
+ event : QWheelEvent
+ The event on the spinbox.
+ """
if QT == 4:
delta = event.delta()
else:
@@ -332,19 +673,34 @@ def wheelEvent(self, event):
self.stepBy(-step)
event.accept()
+
class QLabel(QtWidgets.QLabel):
+ """
+ A reimplementation of the QLabel.
+ The text is center aligned by default.
+ """
def __init__(self, parent, *args, **kwargs):
super(QLabel, self).__init__(parent, *args, **kwargs)
self.setAlignment(QtCore.Qt.AlignCenter)
+
class QSelectLabel(QtWidgets.QLabel):
+ """
+ A reimplementation of the QLabel.
+ The text is selectable by default.
+ """
def __init__(self, parent, *args, **kwargs):
super(QSelectLabel, self).__init__(parent, *args, **kwargs)
self.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse)
+
class QLeftLabel(QtWidgets.QLabel):
+ """
+ A reimplementation of the QLabel.
+ The text is left aligned by default.
+ """
def __init__(self, parent, *args, **kwargs):
super(QLeftLabel, self).__init__(parent, *args, **kwargs)
@@ -353,8 +709,27 @@ def __init__(self, parent, *args, **kwargs):
class QLineEdit(QtWidgets.QLineEdit):
+ """
+ A reimplementation of the QLineEdit.
+ The text is center aligned by default.
+ """
def __init__(self, text='', func=None, parent=None):
+ """
+ Initializes QLineEdit.
+
+ Parameters
+ ----------
+ text : str, optional
+ The initial text, by default this is an empty string.
+ func : function, optional
+ The function that is called when return is pressed.
+ By default no function is called.
+ parent : QWidget, optional
+ The parent widget of the lineedit.
+ This object is passed to QLineEdit.
+ By default None is used.
+ """
super(QLineEdit, self).__init__(parent)
self.setText(str(text))
self.setAlignment(QtCore.Qt.AlignCenter)
@@ -363,18 +738,50 @@ def __init__(self, text='', func=None, parent=None):
class FitQLineEdit(QLineEdit):
+ """
+ A reimplementation of the QLineEdit designed for the fitting parameter frame.
+ Allows connecting parameters from the contextmenu.
+ """
def __init__(self, fitParent, paramName, *args):
+ """
+ Initializes FitQLineEdit.
+
+ Parameters
+ ----------
+ parent : AbstractParamFrame
+ The fitting parameter frame of the lineedit.
+ paramName : str
+ The name of this lineedit.
+ *args
+ Additional arguments are passed to QLineEdit.
+ """
super(FitQLineEdit, self).__init__(*args)
self.fitParent = fitParent
self.paramName = paramName
def contextMenuEvent(self, event):
+ """
+ Creates the context menu, with the Connect Parameter option.
+
+ Parameters
+ ----------
+ event : QEvent
+ The event.
+ """
menu = self.createStandardContextMenu()
menu.addAction('Connect Parameter', self.connectParams)
menu.exec_(event.globalPos())
def connectParams(self, *args):
+ """
+ Opens the ConnectParamsWindow.
+
+ Parameters
+ ----------
+ *args
+ Additional arguments are ignored.
+ """
parametertxtlist = self.fitParent.rootwindow.getParamTextList()
ConnectParamsWindow(self, parametertxtlist, self.paramName, self.fitParent.rootwindow.getTabNames(), self.fitParent.rootwindow.getCurrentTabName(), self.setConnect)
@@ -383,8 +790,29 @@ def setConnect(self, inpTuple):
class ConnectParamsWindow(QtWidgets.QWidget):
+ """
+ The window for connecting fitting parameters.
+ """
def __init__(self, parent, paramTextList, paramName, spectrumNames, currentSpectrum, returnFunc):
+ """
+ Initializes the ConnectParamsWindow.
+
+ Parameters
+ ----------
+ parent : QWidget
+ The parent of the ConnectParamsWindow. This value is passed to QWidget.
+ paramTextList : list of str
+ List with the names of all parameters.
+ paramName : str
+ Name of the lineedit from which this window was opened.
+ spectrumNames : list of str
+ A list of the names of the spectra being fit.
+ currentSpectrum : str
+ The name of the spectrum that is currently open.
+ returnFunc : function
+ The function that should be called when the ok button is pressed.
+ """
super(ConnectParamsWindow, self).__init__(parent)
self.setWindowFlags(QtCore.Qt.Window | QtCore.Qt.Tool)
self.setWindowTitle("Connect Parameter")
@@ -421,12 +849,15 @@ def __init__(self, parent, paramTextList, paramName, spectrumNames, currentSpect
self.okButton.clicked.connect(self.applyAndClose)
self.okButton.setFocus()
self.box = QtWidgets.QDialogButtonBox()
- self.box.addButton(self.cancelButton,QtWidgets.QDialogButtonBox.RejectRole)
- self.box.addButton(self.okButton,QtWidgets.QDialogButtonBox.AcceptRole)
+ self.box.addButton(self.cancelButton, QtWidgets.QDialogButtonBox.RejectRole)
+ self.box.addButton(self.okButton, QtWidgets.QDialogButtonBox.AcceptRole)
self.layout.addWidget(self.box, 2, 0)
self.show()
def applyAndClose(self):
+ """
+ Runs the returnFunc and closes the window.
+ """
paramName = self.paramTextList[self.paramNameEntry.currentIndex()]
returnTuple = (paramName, self.lineEntry.value(), safeEval(self.multEntry.text()), safeEval(self.addEntry.text()), self.spectrumNameEntry.currentIndex())
self.closeEvent()
@@ -434,17 +865,3 @@ def applyAndClose(self):
def closeEvent(self, *args):
self.deleteLater()
-
-
-class specialProgressBar(QtWidgets.QProgressBar):
-
- def __init__(self):
- super(specialProgressBar, self).__init__()
- self.setAlignment(QtCore.Qt.AlignCenter)
- self._text = 'Inactive'
-
- def setText(self, text):
- self._text = text
-
- def text(self):
- return self._text