Exemplo n.º 1
0
def dist_wrap(l1, l2, norm_index=2):
    """ return the average distance modulo 2pi between two lists of angles
    The average is calculated as an n-norm.
    >>> round(dist_wrap([2, 1, 0], [-4, 1, 3]), 7)
    3.013336

    """
    diffs = modtwopi(np.array(l1) - np.array(l2), offset=0)
    return np.linalg.norm(diffs, norm_index)
Exemplo n.º 2
0
def plot_array_phase(freq, ax=plt.gca(), fixp=False, ref_probe=0, ref_offset=0):
    """  Warning - this really should have FS passed as an arg
    Also, to fix 2Pi skips - if there are a number of noisy graphs that 
    should be similar.  Choose the 2pi skip that keeps a graph closest to 
    an already processed one (or the ensemble average?) (how??)

    """

    if not isinstance(freq, int):  # convert reals to the corresponding index
        findex = np.argsort(np.abs(freqs - freq))[0]
        print('freq {freq} index {findex}'.format(**locals())),
    else:
        findex = freq

    phaselist_orig = [np.angle(FTs[isig][findex]) for isig in isigs]
    phaselist = np.copy(phaselist_orig)  # save the original for debugging

    phaselist = fix2pi_skips(phaselist) if fixp else phaselist
    phaselist = phaselist - phaselist[ref_probe] if ref_probe > -999 else phaselist
    if (ref_probe) > -999 and (not fixp):  #  use mod2pi to
        phaselist = modtwopi(phaselist, offset=ref_offset)
    ax.plot(phaselist, label=str('{f:.1f}kHz'.format(f=freqs[findex]/1e3)))
    ax.legend(fontsize='xx-small', loc='best',ncol=1 + min(3, len(isigs)//6))
    plt.show(block=0)
Exemplo n.º 3
0
def dists(a, instances, mask = None, method='euler'):
    """ calculate the RMS (not RSS) distance of the phase set to all phase sets
    based on std in new_mode_identify
    presently takes 1.4 secs for 1Mx14 float32.(100ns/elt
    4ns +,*, 21ns sqrt 43 ns modtwopi 26n (new fmod version)
    """
    if (len(a) != np.shape(instances)[-1]): 
        raise ValueError('shape of phases does not match shape of sample')
    if mask is None: mask=np.arange(len(a))

    if not(hasattr(instances, 'std')):
        print('make phase_array into an np array to speed up 100x')
        # the following assumes it is a structured array - it may be a list~!~
        instances = np.array(instances.tolist())  

    cc = np.tile(a[mask], (np.shape(instances)[0],1))
    # next line is a little faster
    # x=sum(modtwopi((phases[:,sel]-subset[clinds[cl][0]]),offset=0)**2,1)
    #
    # time x=sqrt(average(modtwopi((phases[0:1000000].astype(float32)+1)**2),1))
    # float32 should be faster than float or float16 (worst) but
    # because subset is float32, it is promoted to that precision automatically
    sq = (modtwopi(instances[:,mask]-a, offset=0))**2
    return(np.sqrt(np.average(sq,len(np.shape(instances))-1)))
Exemplo n.º 4
0
def fsplot_phase(input_data, closed=True, ax=None, hold=0, offset=0, block=False):
    """ plot the phase of a flucstruc, optionally inserting the first point
    at the end (if closed=True). Applies to closed arrays (e.g complete 2pi).
    Until Feb 2013, this version did not yet attempt to take into account angles, or check 
    that adjacent channels are adjacent (i.e. ch2-ch1, ch2-c2 etc).
    Channel names are taken from the fs and plotted abbreviated

    1/1/2011: TODO This appears to work only for database = None config
    1/17/2011:  bdb: May be fixed - I had used channel instead of channel.name
    """
    # extract by channels
    ch1n,ch2n,ch21n,dp = [],[],[],[]
    # bdb this line should be replaced by a call to a routine names something
    #like <plotted_width> to help in deciding if the label will fit on the 
    #current graph.
    if ax is None:     ax=pl.gca()
    # why is this repeated below
    max_chars = get_axes_pixcells(ax)[2]/8 # assuming an 10 pt font is 8 wide.
    if (2*len(input_data.dphase)
        *(2+len(input_data.dphase[0].channel_1.name)))> max_chars:
        sep = '\n-'
    else: sep = '-'
    
    #sep = '-'
    # 2013 change order from ch1-ch2 to ch2-ch1 = ch2 - ch1
    for dpn in input_data.dphase:
        ch1n.append(dpn.channel_1.name)
        ch2n.append(dpn.channel_2.name)
        ch21n.append(dpn.channel_2.name+sep+dpn.channel_1.name)
        dp.append(dpn.delta)

    min_length = max(1,40/len(input_data.channels))    
    # min_length - min_length???
    short_names_1,p,s = split_names(ch1n, min_length=2)  # need to break up loops to do this
    short_names_2,p,s = split_names(ch2n, min_length=5)  # 

# need to know how big the shortened names are before deciding on the separator
    if (2*len(input_data.dphase)*(2+len(short_names_1[0])))> max_chars:
        sep = '\n-'
    else: sep = '-'

    ch21n = [ch2n[i]+sep+ch1n[i] for i in range(len(ch1n))]
    short_ch21n = [short_names_2[i]+sep+short_names_1[i] 
                   for i in range(len(short_names_1))]

    # correct result for a diag that doesn MP1,2,3,4,5,6,1, and not closed
    #ch21n = ['MP2-MP1', 'MP3-MP2', 'MP4-MP3', 'MP5-MP4', 'MP6-MP5', 'MP1-MP6']
    # if closed, and only 1-6 in the file, want the same!

    if closed:   # ch2 will be MP1, ch1 will be MP6   MP1-MP6
        ch1n.append(ch2n[-1])
        ch2n.append(ch1n[0])
        ch21n.append(ch2n[-1]+sep+ch1n[0])
        short_ch21n.append(short_names_2[-1]+sep+short_names_1[0])
        #dp.insert(0,dp[-1])
        # closed means use the phase diff from the ends
        # sign bug fixed here - made closed opposite sign to open..
        dp=np.append(dp,modtwopi(-np.sum(dp),offset=offset))

    #dp = fix2pi_skips(dp, around=offset)
    dp = modtwopi(dp, offset=offset)

    if hold == 0: ax.clear()

    # This is a kludgy way to read coordinates.  Should be through acquisition.base or acquisition.'device'
    Phi = np.array([2*np.pi/360*float(pyfusion.config.get
                                      ('Diagnostic:{cn}'.
                                       format(cn=c.name), 
                                       'Coords_reduced')
                                      .split(',')[0]) 
                    for c in input_data.channels])
    Theta = np.array([2*np.pi/360*float(pyfusion.config.get
                                        ('Diagnostic:{cn}'.
                                         format(cn=c.name), 
                                         'Coords_reduced')
                                        .split(',')[1]) 
                      for c in input_data.channels])

    if closed: 
        Phi = np.append(Phi, Phi[0])
        Theta = np.append(Theta, Theta[0])

    if len(np.unique(Theta)) > 1:
        AngName = 'Theta'
        Ang = Theta
        dAngfor1 = np.pi/13  #dAngfor1 is the average coil dph for M=1
        span = (np.pi)/13  # span is the average coil spacing in radians
    else:
        AngName = 'Phi'
        Ang = Phi
        dAngfor1 = (2*np.pi)/6
        span = 2*np.pi/6
        
    # expect Phi from ~.2 to twopi+.2 (if closed)
    Angfix = fix2pi_skips(Ang,around=3.5)

    # Here use fix2pi_skips, as we want the coil location angle to 
    # increase monotonically - the raw numbers in .cfg may not start at zero 
    # need to make sure the right dp is divided by the right dPhi!
    ax.plot(fix2pi_skips(Angfix[0:-1],around=np.pi),dp/np.diff(Angfix)*span,
            '+-',label='dp/d'+AngName[0])
    ax.plot(fix2pi_skips(Angfix[0:-1],around=np.pi),dp,'o-', label='d'+AngName)
    ax.set_xlim([ax.get_xlim()[0],
                 ax.get_xlim()[1]+np.average(np.diff(Angfix))])
    ax.plot(ax.get_xlim(),[0,0],':k',linewidth=0.5)
    for N in (-3,-2,-1,1,2,3): ax.plot(ax.get_xlim(),[N*dAngfor1,N*dAngfor1],':r',linewidth=0.5)
    tot=np.sum(dp)
    over = Angfix[-1] - Angfix[0]
    print(tot)
    if closed: # only makes sense to draw a mean dp line if closed
        ax.plot(ax.get_xlim(),[tot/(2*np.pi),tot/(2*np.pi)],':b',linewidth=0.5)

    ax.legend(prop=FontProperties(size='small'))
    ax.set_title('sum = {s:.2f} over {o:.2f} ~ {r:.1f}'
                 .format(s=tot,o=over, r=tot/over))
    debug_(pyfusion.DEBUG, 1, key='fs_phase')
    #ax.set_xticks(range(len(dp)))
    ax.set_xticks(Angfix)
    ax.set_xticklabels(short_ch21n)
    pl.show(block=block)
Exemplo n.º 5
0
from pyfusion.data.DA_datamining import DA
from pyfusion.acquisition.read_text_pyfusion import read_text_pyfusion, plot_fs_DA, merge_ds
from pyfusion.visual.window_manager import rmw, cmw, omw, lmw, smw
from pyfusion.utils.utils import fix2pi_skips, modtwopi
from pyfusion.visual.sp import off, on, tog
from pyfusion.data.convenience import between, bw, btw, decimate, his, broaden


dd=DA('W7X_MIR/DAMIRNOV_41_13_nocache_15_3m_2018fl.zip')
dd.info()
fig4, axs4=plt.subplots(4,1)
figfs, axf=plt.subplots(1,1)
plot_fs_DA(dd, ax=axf)
w6=where((btw(dd['freq'],4,8)) & (dd['amp']>0.0015) & (dd['t_mid']>3.2) &(dd['shot'] == 180904035))[0]
plot_fs_DA(dd, ax=axf, inds=w6,marker='s',ms=300,alpha=0.5)
axs4[0].plot(array([modtwopi(ph,offset=0) for ph in dd['phases'][w6]]).T,'c',lw=.5)
w6=where((btw(dd['freq'],4,8)) & (dd['amp']>0.015) & (dd['t_mid']>3.2) &(dd['shot'] == 180904035))[0]
axs4[0].plot(array([modtwopi(ph,offset=0) for ph in dd['phases'][w6]]).T,'b',lw=.5)
axs4[0].set_title('4-8kHz, after 3.2s')
w0=where((btw(dd['freq'],0,2)) & (dd['amp']>0.0015) & (dd['t_mid']>3.2) &(dd['shot'] == 180904035))[0]
plot_fs_DA(dd, ax=axf, inds=w0,marker='s',ms=300,alpha=0.5)
axs4[1].plot(array([modtwopi(ph,offset=0) for ph in dd['phases'][w0]]).T,'b',lw=.5)
axs4[1].set_title('0-2kHz, > 3.2s')
w6e=where((btw(dd['freq'],4,12)) & (dd['amp']>0.015) & (dd['t_mid']<3.2) &(dd['shot'] == 180904035))[0]
plot_fs_DA(dd, ax=axf, inds=w6e,marker='^',ms=300,alpha=0.5)
axs4[2].plot(array([modtwopi(ph,offset=0) for ph in dd['phases'][w6e]]).T,'c',lw=.5)
w6e=where((btw(dd['freq'],4,12)) & (dd['amp']>0.025) & (dd['t_mid']<3.2) &(dd['shot'] == 180904035))[0]
axs4[2].plot(array([modtwopi(ph,offset=0) for ph in dd['phases'][w6e]]).T,'b',lw=1)
axs4[2].set_title('4-12kHz, before 3.2s')
axs4[3].plot(array([modtwopi(ph,offset=.5) for ph in dd['phases']])[::5].T,'b',lw=.015)
axs4[3].set_title('all')
Exemplo n.º 6
0
def dist2(a,b, method='euler'):
    ax = (max(len(np.shape(a)),len(np.shape(b)))) - 1
    return(np.sum((modtwopi((np.array(a)- np.array(b)),offset=0)**2),ax))
Exemplo n.º 7
0
    if DAfile != '':
        da = DA(DAfile, load=1)
    else:
        print('try for a da in locals()')
        try:
            da
        except NameError as reason:
            print(' no da - did you use run -i?')
    wh = da['indx']  # all of them
    #wh = np.where((btw(da['freq'],2,4)) & (da['amp']>0.012) )[0]
    wh = np.where(da['shot'] == 180904035)[0]
    phs = da['phases'][wh].tolist()
    inds = da['indx'][wh].tolist()

    ctrs = np.mean(modtwopi(phs, 0), 0)
    num = len(ctrs)

    print(len(wh))

    for left in range(len(phs), min_left, -1):
        if version == 1:
            ctrs = np.mean(modtwopi(phs, 0), 0)
        dists = [dist_wrap(ctrs, phases) / num for phases in phs]
        if np.max(dists) < tolerance:
            break
        worst = np.argmax(dists)
        phs.pop(worst)
        inds.pop(worst)
        """
        worst = np.argsort(dists)[::-1]  # this won't work as position in list changes....
Exemplo n.º 8
0
def fsplot_phase(input_data,
                 closed=True,
                 ax=None,
                 hold=0,
                 offset=0,
                 AngName=None,
                 block=False):
    """ plot the phase of a flucstruc, optionally inserting the first point
    at the end (if closed=True). Applies to closed arrays (e.g complete 2pi).
    Until Feb 2013, this version did not yet attempt to take into account angles, or check 
    that adjacent channels are adjacent (i.e. ch2-ch1, ch2-c2 etc).
    Channel names are taken from the fs and plotted abbreviated

    1/1/2011: TODO This appears to work only for database = None config
    1/17/2011:  bdb: May be fixed - I had used channel instead of channel.name
    """
    # extract by channels
    ch1n, ch2n, ch21n, dp = [], [], [], []
    # bdb this line should be replaced by a call to a routine names something
    #like <plotted_width> to help in deciding if the label will fit on the
    #current graph.
    if ax is None: ax = pl.gca()
    # why is this repeated below
    max_chars = get_axes_pixcells(
        ax)[2] / 8  # assuming an 10 pt font is 8 wide.
    if (2 * len(input_data.dphase) *
        (2 + len(input_data.dphase[0].channel_1.name))) > max_chars:
        sep = '\n-'
    else:
        sep = '-'

    #sep = '-'
    # 2013 change order from ch1-ch2 to ch2-ch1 = ch2 - ch1
    for dpn in input_data.dphase:
        ch1n.append(dpn.channel_1.name)
        ch2n.append(dpn.channel_2.name)
        ch21n.append(dpn.channel_2.name + sep + dpn.channel_1.name)
        dp.append(dpn.delta)

    min_length = max(1, 40 / len(input_data.channels))
    # min_length - min_length???
    short_names_1, p, s = split_names(
        ch1n, min_length=2)  # need to break up loops to do this
    short_names_2, p, s = split_names(ch2n, min_length=4)  # used to be 5

    # need to know how big the shortened names are before deciding on the separator
    if (2 * len(input_data.dphase) * (2 + len(short_names_1[0]))) > max_chars:
        sep = '\n-'
    else:
        sep = '-'

    ch21n = [ch2n[i] + sep + ch1n[i] for i in range(len(ch1n))]
    short_ch21n = [
        short_names_2[i] + sep + short_names_1[i]
        for i in range(len(short_names_1))
    ]

    # correct result for a diag that doesn MP1,2,3,4,5,6,1, and not closed
    #ch21n = ['MP2-MP1', 'MP3-MP2', 'MP4-MP3', 'MP5-MP4', 'MP6-MP5', 'MP1-MP6']
    # if closed, and only 1-6 in the file, want the same!

    if closed:  # ch2 will be MP1, ch1 will be MP6   MP1-MP6
        ch1n.append(ch2n[-1])
        ch2n.append(ch1n[0])
        ch21n.append(ch2n[-1] + sep + ch1n[0])
        short_ch21n.append(short_names_2[-1] + sep + short_names_1[0])
        #dp.insert(0,dp[-1])
        # closed means use the phase diff from the ends
        # sign bug fixed here - made closed opposite sign to open..
        dp = np.append(dp, modtwopi(-np.sum(dp), offset=offset))

    #dp = fix2pi_skips(dp, around=offset)
    dp = modtwopi(dp, offset=offset)

    if hold == 0: ax.clear()

    # This is a kludgey way to read coordinates.  Should be through acquisition.base or acquisition.'device'
    Phi = np.array([
        2 * np.pi / 360 * float(
            pyfusion.config.get('Diagnostic:{cn}'.format(cn=c.config_name),
                                'Coords_reduced').split(',')[0])
        for c in input_data.channels
    ])
    Theta = np.array([
        2 * np.pi / 360 * float(
            pyfusion.config.get('Diagnostic:{cn}'.format(cn=c.config_name),
                                'Coords_reduced').split(',')[1])
        for c in input_data.channels
    ])

    if closed:
        Phi = np.append(Phi, Phi[0])
        Theta = np.append(Theta, Theta[0])

    # kludgey - needed to deal with Shaun's array - should
    # really convert form cylindrical
    if AngName is not 'Phi' and len(np.unique(Theta)) > 1:
        AngName = 'Theta'
        Ang = Theta
        dAngformeq1 = np.pi / 13  #dAngformeq1 is the average coil dph for M=1
        span = (np.pi) / 13  # span is the average coil spacing in radians
    else:
        AngName = 'Phi'
        Ang = Phi
        dAngformeq1 = (2 * np.pi) / 6  # seems hardwired for LHD or shaun??
        span = 2 * np.pi / 6

    if closed:
        dAngformeq1 = (2 * np.pi) / len(Ang)  # bdb 2019 - overide if closed
        span = dAngformeq1  # why two veraible for the same thing - are they same?
    # expect Phi from ~.2 to twopi+.2 (if closed)
    Angfix = fix2pi_skips(Ang, around=3.5)

    # Here use fix2pi_skips, as we want the coil location angle to
    # increase monotonically - the raw numbers in .cfg may not start at zero
    # need to make sure the right dp is divided by the right dPhi!
    ax.plot(
        fix2pi_skips(Angfix[0:-1], around=np.pi),
        dp / np.diff(Angfix) * span,
        '+-',
        label='dp/d' + AngName[0],
        lw=0.2,
    )
    ax.plot(fix2pi_skips(Angfix[0:-1], around=np.pi),
            dp,
            'o-',
            label='d' + AngName)
    ax.set_xlim(
        [ax.get_xlim()[0],
         ax.get_xlim()[1] + np.average(np.diff(Angfix))])
    ax.plot(ax.get_xlim(), [0, 0], ':k', linewidth=0.5)
    for N in (-3, -2, -1, 1, 2, 3):
        ax.plot(ax.get_xlim(), [N * dAngformeq1, N * dAngformeq1],
                ':m',
                linewidth=0.2,
                label=['', '~dth(m=1)'][N == 1])
    tot = np.sum(dp)
    over = Angfix[-1] - Angfix[0]
    print(tot)
    if closed:  # only makes sense to draw a mean dp line if closed
        ax.plot(ax.get_xlim(), [tot / (2 * np.pi), tot / (2 * np.pi)],
                ':b',
                linewidth=0.5)

    ax.legend(prop=FontProperties(size='xx-small'))
    ax.set_title('sum = {s:.2f} over {o:.2f} ~ {r:.1f}'.format(s=tot,
                                                               o=over,
                                                               r=tot / over))
    debug_(pyfusion.DEBUG, 1, key='fs_phase')
    #ax.set_xticks(range(len(dp)))
    ax.set_xticks(Angfix)
    # think this out better - e.g. this 128 should be adjusted according to max_chars
    ax.set_xticklabels(short_ch21n,
                       fontsize=min(128 // len(short_ch21n), 10),
                       rotation=['horizontal', 'vertical'][len(Angfix) > 8])
    print('block = ', block)
    pl.show(block=block)