Beispiel #1
0
def read_temperature_UDA(shot,time,**properties):
    """
    notes:
        needs NaN checking (replace with interpolated values)
        this script heavily relies on the structure of UDA - please contant Stuart Henderson for updates
    """

    print("reading temperature from UDA")

    try:
        import pyuda
        udaClient=pyuda.Client()
        getdata=udaClient.get
        import numpy as np
    except:
        raise ImportError("ERROR: read_temperature_UDA could not import pyuda!\nreturning\n")

    equilibrium=classes.input_classes.equilibrium.Equilibrium(ID='',data_format='UDA',shot=shot,time=time) #needs to read corresponding equilibrium
    input_data={}

    if properties['species']=='electrons':

        if shot<23000:
            signal_T='atm_te'
            signal_R='atm_R'
        else:
            signal_T='ayc_te'
            signal_R='ayc_r'

        T=getdata(signal_T,shot)
        R_data=getdata(signal_R,shot) #electron and ion temperature signals are stored against different radial bases - must access another dataset for electrons
        time_grid=T.dims[0].data
        time_index=np.abs(time_grid-time).argmin()[0] #figure out what time we are wanting to output (pick closest)
        R_grid=R_data.data[time_index]
    
    elif properties['species']=='ions':

        T=getdata('act_ss_temperature',shot)
        time_grid=T.dims[0].data
        time_index=np.abs(time_grid-time).argmin()[0] #figure out what time we are wanting to output (pick closest)
        R_grid=T.dims[1].data 

    T=T.data[time_index,:]
    psi_grid=processing.utils.RZ_to_Psi(R_grid,np.full(len(R_grid),0.0),equilibrium) #assume measurements are at along Z=0
    interpolator_temperature=processing.utils.interpolate_1D(psi_grid,T)

    input_data['flux_pol']=np.linspace(np.min(psi_grid),np.max(psi_grid),200)
    input_data['flux_pol_norm']=(input_data['flux_pol']-np.min(input_data['flux_pol']))/(np.max(input_data['flux_pol']-np.min(input_data['flux_pol'])))
    input_data['T']=interpolator_temperature(input_data['flux_pol'])

    print("finished reading temperature from UDA")

    return input_data
Beispiel #2
0
    def __init__(self, pulse):

        self.client = pyuda.Client()  # get the pyuda client

        # Poloidal magnetic flux per toroidal radian as a function of (Z,R) and timebase
        self.psi = self.client.get("efm_psi(r,z)", pulse)

        self.time_slices = self.psi.dims[0].data

        # Psi grid axes f(nr), f(nz)
        self.r = self.client.get("efm_grid(r)", pulse)
        self.z = self.client.get("efm_grid(z)", pulse)

        # f profile
        self.f = self.client.get(
            "efm_f(psi)_(c)",
            pulse)  # Poloidal current flux function, f=R*Bphi; f(psin, C)

        self.psi_r = self.client.get(
            "efm_psi(r)", pulse
        )  #poloidal magnetic flux per toroidal radian as a function of radius at Z=0

        # Poloidal magnetic flux per toroidal radian at the plasma boundary and magnetic axis
        self.psi_lcfs = self.client.get("efm_psi_boundary", pulse)
        self.psi_axis = self.client.get("efm_psi_axis", pulse)

        # Plasma current
        self.plasma_current = self.client.get("efm_plasma_curr(C)", pulse)

        # Reference vaccuum toroidal B field at R = efm_bvac_r
        self.b_vacuum_magnitude = self.client.get("efm_bvac_val", pulse)

        self.b_vacuum_radius = self.client.get("efm_bvac_r", pulse)

        # Magnetic axis co-ordinates
        self.axis_coord_r = self.client.get("efm_magnetic_axis_r", pulse)
        self.axis_coord_z = self.client.get("efm_magnetic_axis_z", pulse)

        #minor radius
        self.minor_radius = self.client.get("EFM_MINOR_RADIUS", pulse)

        #lcfs boundary polygon
        self.lcfs_poly_r = self.client.get("efm_lcfs(r)_(c)", pulse)
        self.lcfs_poly_z = self.client.get("efm_lcfs(z)_(c)", pulse)

        # Number of LCFS co-ordinates
        self.nlcfs = self.client.get("EFM_LCFS(N)_(C)", pulse)

        # time slices when plasma is present
        self.plasma_times = self.client.get("EFM_IP_TIMES", pulse)

        self.time_range = self.time_slices.min(), self.time_slices.max()
Beispiel #3
0
"""
This script demonstrates loading the reconstruction grid for the lower
divertor bolometers, and plotting it alongside the MAST-U passive
structures.
"""
import matplotlib.pyplot as plt
import pyuda
from cherab.mastu.bolometry import load_standard_voxel_grid


grid = load_standard_voxel_grid('sxdl')
client = pyuda.Client()
passive_structures = client.geometry('/passive/efit', 50000)

fig, ax = plt.subplots()
grid.plot(ax=ax)
passive_structures.plot(ax_2d=ax, color='k')
ax.set_ylim(top=-1.5)

# Reduce the line width of the grid edges to make it clearer
for patch_collection in ax.collections:
    patch_collection.set_linewidth(0.7)

plt.show()
Beispiel #4
0
    def __init__(self, pulse):

        self.client = pyuda.Client()  # get the pyuda client

        # Poloidal magnetic flux per toroidal radian as a function of (Z,R) and timebase
        self.psi = self.client.get("efm_psi(r,z)", pulse)

        self.time_slices = self.psi.dims[0].data

        # Psi grid axes f(nr), f(nz)
        self.r = self.client.get("efm_grid(r)", pulse)
        self.z = self.client.get("efm_grid(z)", pulse)

        # f profile
        self.f = self.client.get("efm_f(psi)_(c)", pulse)# Poloidal current flux function, f=R*Bphi; f(psin, C)

        # q profile
        self.q = self.client.get("efm_q(psi)_(c)", pulse)

        self.psi_r = self.client.get("efm_psi(r)", pulse) #poloidal magnetic flux per toroidal radian as a function of radius at Z=0

        # Poloidal magnetic flux per toroidal radian at the plasma boundary and magnetic axis
        self.psi_lcfs = self.client.get("efm_psi_boundary", pulse)
        self.psi_axis = self.client.get("efm_psi_axis", pulse)

        # Plasma current
        self.plasma_current = self.client.get("efm_plasma_curr(C)", pulse)

        # Reference vaccuum toroidal B field at R = efm_bvac_r
        self.b_vacuum_magnitude = self.client.get("efm_bvac_val", pulse)

        self.b_vacuum_radius = self.client.get("efm_bvac_r", pulse)

        # Magnetic axis co-ordinates
        self.axis_coord_r = self.client.get("efm_magnetic_axis_r", pulse)
        self.axis_coord_z = self.client.get("efm_magnetic_axis_z", pulse)

        # X point coordinates
        xpoint1r = self.client.get("efm_xpoint1_r(c)", pulse).data
        xpoint1z = self.client.get("efm_xpoint1_z(c)", pulse).data
        xpoint2r = self.client.get("efm_xpoint2_r(c)", pulse).data
        xpoint2z = self.client.get("efm_xpoint2_z(c)", pulse).data
        self.xpoints = [
            (Point2D(r1, z1), Point2D(r2, z2))
            for (r1, z1, r2, z2) in zip(xpoint1r, xpoint1z, xpoint2r, xpoint2z)
        ]

        #minor radius
        self.minor_radius = self.client.get("efm_minor_radius", pulse)

        #lcfs boundary polygon
        self.lcfs_poly_r = self.client.get("efm_lcfs(r)_(c)", pulse)
        self.lcfs_poly_z = self.client.get("efm_lcfs(z)_(c)", pulse)

        # Number of LCFS co-ordinates
        self.nlcfs = self.client.get("efm_lcfs(n)_(c)", pulse)

        # limiter boundary polygon
        self.limiter_poly_r = self.client.get("efm_limiter(r)", pulse)
        self.limiter_poly_z = self.client.get("efm_limiter(z)", pulse)

        # Number of limiter co-ordinates
        self.nlimiter = self.client.get("efm_limiter(n)", pulse)

        # time slices when plasma is present
        self.plasma_times = self.client.get("efm_ip_times", pulse)

        self.time_range = self.time_slices.min(), self.time_slices.max()
def read_equilibrium_UDA(shot,time):
    """
    reads equilibrium from analysed EFIT signals from MAST UDA database

    notes:

    args:
        shot - target shot number to read
        time - fetch equilibrium at this time
    """

    print("reading equilibrium from UDA")

    input_data={}

    try:
        import pyuda
        udaClient=pyuda.Client()
        getdata=udaClient.get
        import numpy as np
    except:
        raise ImportError("ERROR: read_equilibrium_UDA could not import pyuda!\nreturning\n")

    #time dependent data first
    input_data['psirz']=getdata('efm_psi(r,z)',       shot)
    input_data['simag']=getdata('efm_psi_axis',       shot)
    input_data['sibry']=getdata('efm_psi_boundary',   shot)
    input_data['current']=getdata('efm_plasma_curr(C)', shot)
    input_data['bcentr']=getdata('efm_bvac_val',       shot)
    input_data['rcentr']=getdata('efm_bvac_r',       shot)
    input_data['pres']=getdata('efm_p(psi)_(c)',shot)
    input_data['fpol']=getdata('efm_f(psi)_(c)',shot)
    input_data['rmaxis']=getdata('efm_magnetic_axis_r',shot)
    input_data['zmaxis']=getdata('efm_magnetic_axis_z',shot)
    input_data['ffprime']=getdata('efm_ffprime',shot)
    input_data['pprime']=getdata('efm_pprime',shot)
    input_data['qpsi']=getdata('efm_q(psi)_(c)',shot)
    input_data['lcfs_n']=getdata('efm_lcfs(n)_(c)',shot)
    input_data['lcfs_r']=getdata('efm_lcfs(r)_(c)',shot)
    input_data['lcfs_z']=getdata('efm_lcfs(z)_(c)',shot)
    input_data['limitr']=getdata('efm_limiter(n)',shot) #limiter data not on time base but contains single time coordinate, so read in here
    input_data['rlim']=getdata('efm_limiter(r)',shot)
    input_data['zlim']=getdata('efm_limiter(z)',shot)

    #redefine read time based on available converged EFIT equilibria constructions 
    time_index=np.abs(input_data['psirz'].time.data-time).argmin()
    time_new=input_data['psirz'].time.data[time_index]

    #go through time dependent data and pick closest times
    for key in input_data:
        #print(key) #to check times
        time_index=np.abs(input_data[key].time.data-time_new).argmin()
        #print(input_data[key].time.data[time_index]) #to check times
        input_data[key]=np.array(input_data[key].data[time_index])

    input_data['lcfs_r']=input_data['lcfs_r'][0:input_data['lcfs_n']] #LCFS data seems to have junk on the end, so crop accordingly
    input_data['lcfs_z']=input_data['lcfs_z'][0:input_data['lcfs_n']]

    input_data['psirz']=input_data['psirz'].T

    input_data['R_1D']=np.asarray(getdata('efm_grid(r)',shot).data[0,:])
    input_data['Z_1D']=np.asarray(getdata('efm_grid(z)',shot).data[0,:])
    input_data['nR_1D']=np.asarray(getdata('efm_nw',shot).data)
    input_data['nZ_1D']=np.asarray(getdata('efm_nh',shot).data)
    input_data['rdim']=input_data['R_1D'][-1]-input_data['R_1D'][0]
    input_data['rleft']=input_data['R_1D'][0]
    input_data['zdim']=input_data['Z_1D'][-1]-input_data['Z_1D'][0]
    input_data['zmid']=np.asarray((input_data['Z_1D'][-1]+input_data['Z_1D'][0])*.5)
    input_data['flux_pol']=np.linspace(input_data['simag'],input_data['sibry'],100)
    
    '''
    input_data['rlim'] = np.array([
    0.195, 0.195, 0.280, 0.280, 0.280, 0.175,
    0.175, 0.190, 0.190, 0.330, 0.330, 0.535,
    0.535, 0.755, 0.755, 0.755, 1.110, 1.655,
    1.655, 1.655, 2.000, 2.000, 2.000, 2.000,
    2.000, 1.655, 1.655, 1.655, 1.110, 0.755,
    0.755, 0.755, 0.535, 0.535, 0.330, 0.330,
    0.190, 0.190, 0.175, 0.175, 0.280, 0.280,
    0.280, 0.195, 0.195])

    input_data['zlim'] = np.array([
    0.000, 1.080, 1.220, 1.450, 1.670, 1.670,
    1.720, 1.820, 1.905, 2.000, 2.000, 2.000,
    2.000, 2.000, 1.975, 1.826, 1.826, 1.826,
    1.975, 2.000, 2.000, 0.300, 0.000,-0.300,
    -2.000,-2.000,-1.975,-1.826,-1.826,-1.826,
    -1.975,-2.000,-2.000,-2.000,-2.000,-2.000,
    -1.905,-1.820,-1.720,-1.670,-1.670,-1.450,
    -1.220,-1.080, 0.000])'''

    print("finished reading equilibrium from UDA")

    return input_data
Beispiel #6
0
def load_omas_uda(server=None,
                  port=None,
                  pulse=None,
                  run=0,
                  paths=None,
                  imas_version=os.environ.get(
                      'IMAS_VERSION', omas_rcparams['default_imas_version']),
                  skip_uncertainties=False,
                  skip_ggd=True,
                  verbose=True):
    '''
    Load UDA data to OMAS

    :param server: UDA server

    :param port: UDA port

    :param pulse: UDA pulse

    :param run: UDA run

    :param paths: list of paths to load from IMAS

    :param imas_version: IMAS version

    :param skip_uncertainties: do not load uncertain data

    :param skip_ggd: do not load ggd structure

    :param verbose: print loading progress

    :return: OMAS data set
    '''

    if pulse is None or run is None:
        raise Exception('`pulse` and `run` must be specified')

    if server is not None:
        pyuda.Client.server = server
    elif not os.environ['UDA_HOST']:
        raise pyuda.UDAException('Must set UDA_HOST environmental variable')

    if port is not None:
        pyuda.Client.port = port
    elif not os.environ['UDA_PORT']:
        raise pyuda.UDAException('Must set UDA_PORT environmental variable')

    # set this to get pyuda metadata (maybe of interest for future use):
    # pyuda.Client.set_property(pyuda.Properties.PROP_META, True)

    client = pyuda.Client()

    # if paths is None then figure out what IDS are available and get ready to retrieve everything
    if paths is None:
        requested_paths = [[
            structure
        ] for structure in list_structures(imas_version=imas_version)]
    else:
        requested_paths = map(p2l, paths)

    available_ds = []
    for ds in numpy.unique([p[0] for p in requested_paths]):
        if ds in add_datastructures.keys():
            continue

        if uda_get(client, [ds, 'ids_properties', 'homogeneous_time'], pulse,
                   run) is None:
            if verbose:
                print('- ', ds)
            continue
        if verbose:
            print('* ', ds)
        available_ds.append(ds)

    ods = ODS(consistency_check=False)
    for k, ds in enumerate(available_ds):
        filled_paths_in_uda(ods,
                            client,
                            pulse,
                            run,
                            load_structure(ds, imas_version=imas_version)[1],
                            path=[],
                            paths=[],
                            requested_paths=requested_paths,
                            skip_uncertainties=skip_uncertainties,
                            skip_ggd=skip_ggd,
                            perc=[
                                float(k) / len(available_ds) * 100,
                                float(k + 1) / len(available_ds) * 100,
                                float(k) / len(available_ds) * 100
                            ])
    ods.consistency_check = True
    ods.prune()
    if verbose:
        print()
    return ods
Beispiel #7
0
    def __init__(self, shot):

        """
        Pulls some useful parameters from the database for the MSE diagnostic. Requires a shotnumber as an input.
        :param shot: (int) Shot number.
        """

        self.client = pyuda.Client() #client to retrieve data

        self.beam_present = self.client.get('ams_beam_ok', shot)

        if self.beam_present.data == 0.:
            print('Beam not present - no MSE data available!')
            return
        else:
            print('Beam present - MSE data available!')
            pass

        self.channels = self.client.get('ams_ch', shot)

        # Fibers connected to each channel

        self.fibers = self.client.get('ams_md', shot)

        # Polarization angle (proportional to pitch angle in absence of Er)

        self.gamma = self.client.get('ams_gamma', shot)

        self.gamma_noise = self.client.get('ams_gammanoise', shot)

        # Magnetic Pitch angle tan(gamma)*(A5/A0) = tan(pitch_angle) where A0 and A5 are geometry coefficients

        self.pitch_angle = self.client.get('ams_pitcha', shot)

        self.pitch_angle_noise = self.client.get('ams_pitchanoise', shot)

        # Major radius and Time axis

        self.time_axis = self.gamma.dims[0].data

        self.time_range = self.time_axis.min(), self.time_axis.max()

        self.major_radius = self.client.get('ams_rpos', shot)

        # Stokes vectors and errors

        self.S0 = self.client.get('ams_s0', shot)

        self.S0_noise = self.client.get('ams_s0noise', shot)

        self.S1 = self.client.get('ams_s1noise', shot)

        self.S1_noise = self.client.get('ams_s1noise', shot)

        self.S2 = self.client.get('ams_s2noise', shot)

        self.S2_noise = self.client.get('ams_s2noise', shot)

        self.S3 = self.client.get('ams_s3noise', shot)

        self.S3_noise = self.client.get('ams_s3noise', shot)

        # View geometry data

        self.view_geometry = self.client.get('ams_viewstr', shot)

        # Horizontal co-ordinates of the MSE fibres on the focal plane of the collection lens

        self.vx0 = self.client.get('ams_vx0', shot)

        self.vy0 = self.client.get('ams_vy0', shot)

        # Cosine between the line of sight and beam direction for each sightline

        self.cosbeam = self.client.get('ams_cosbeam', shot)

        # Photoelastic Modulator parameters (driving frequency and their retardance)

        self.PEM1_frequency = self.client.get('ams_pem1_freq', shot)

        self.PEM1_retardance = self.client.get('ams_retar1', shot)

        self.PEM2_frequency = self.client.get('ams_pem2_freq', shot)

        self.PEM2_retardance = self.client.get('ams_retar2', shot)

        self.A_coefficients = self.client.get('AMS_ACOEFF', shot)

        #A coefficients related to the geometry of the diagnostic. There is a separate A coefficient for each line of sight, so 36x6 coefficients

        self.A0 = self.A_coefficients.data[0,0,:]

        self.A1 = self.A_coefficients.data[0,1,:]

        self.A2 = self.A_coefficients.data[0,2,:]

        self.A3 = self.A_coefficients.data[0,3,:]

        self.A4 = self.A_coefficients.data[0,4,:]

        self.A5 = self.A_coefficients.data[0,5,:]
Beispiel #8
0
def load_default_bolometer_config(bolometer_id, parent=None, shot=50000):
    """
    Load the bolometer confituration for a given bolometer ID.

    :param bolometer_id: the name of the bolometer camera,
    in the form "chamber - camera"
    :param parent: the parent node of the resulting bolometer node
    :param shot: read the bolometer state at the given shot
    <shot> can be either a shot number, in which case the geometry is
    looked up in pyuda, or a string containing the path to a local
    netCDF file, e.g. '/home/jlovell/Bolometer/bolo_geom_fromscript.nc',
    in which case the geometry is loaded from that file. The file must
    conform to the same specification as that in the machine
    description, described in CD/MU/05410.

    :return bolometer: the BolometerCamera object for the requested camera.
    """
    try:
        chamber, camera_name = [
            elem.strip() for elem in bolometer_id.split('-')
        ]
    except KeyError:
        raise ValueError(
            "Bolometer camera ID '{}' not recognised.".format(bolometer_id))

    if chamber.lower() not in ('sxdl', 'core'):
        raise ValueError('Chamber must be "SXDL" or "CORE"')

    client = pyuda.Client()
    try:
        bolometers = client.geometry('/bolo/{}'.format(chamber.lower()),
                                     shot,
                                     cartesian_coords=True).data
    except AttributeError:
        raise pyuda.UDAException(
            "Couldn't retrieve bolometer geometry data from UDA.")
    camera_id = 'MAST-U {} - {} Bolometer'.format(chamber, camera_name)
    bolometer_camera = BolometerCamera(name=camera_id, parent=parent)
    # FIXME: When reading from local files with UDA, need an extra data child.
    # This is due to a bug in the pyuda geometry wrapper for local files.
    try:
        slits = bolometers['/slits/data']
    except KeyError:
        slits = bolometers['/data/slits/data']
    slit_objects = {}
    for slit in slits:
        try:
            curvature_radius = slit.curvature_radius
        except AttributeError:
            curvature_radius = 0
        # Only include slits in the requested camera
        # Slit IDs are of the form "MAST-U <chamber> - <camera> Slit <N>"
        slit_camera = slit.id[0].split('-')[2].split()[0]
        if slit_camera != camera_name:
            continue
        slit_objects[slit.id[0]] = BolometerSlit(
            basis_x=uda_to_vector(slit['basis_1']),
            basis_y=uda_to_vector(slit['basis_2']),
            centre_point=uda_to_point(slit['centre_point']),
            csg_aperture=True,
            dx=slit.width,
            dy=slit.height,
            curvature_radius=curvature_radius,
            slit_id=slit.id[0],
            parent=bolometer_camera,
        )

    try:
        foils = bolometers['/foils/data']
    except KeyError:
        foils = bolometers['/data/foils/data']
    for foil in foils:
        # Only include foils in the requested camera
        # Foil IDs are of the form "MAST-U <chamber> - <camera> CH<N>"
        foil_camera = foil.id[0].split('-')[2].split()[0]
        if foil_camera != camera_name:
            continue
        foil = BolometerFoil(
            basis_x=uda_to_vector(foil['basis_1']),
            basis_y=uda_to_vector(foil['basis_2']),
            centre_point=uda_to_point(foil['centre_point']),
            dx=foil.width,
            dy=foil.height,
            curvature_radius=foil.curvature_radius,
            detector_id=foil.id[0],
            slit=slit_objects[foil.slit_id[0]],
            parent=bolometer_camera,
        )
        bolometer_camera.add_foil_detector(foil)

    return bolometer_camera
Beispiel #9
0
'''
This code is used to take the basic EFIT run used for a shot on MAST. Take the necessary parameters in order to
calculate B field components"

NB: To load OLD MAST data with pyIDAM. in the terminal: module load idam/1.6.3
    To load MAST-U data using pyuda: module unload idam/1.6.3, module load uda

'''

import pyuda
import numpy as np
import matplotlib.pyplot as plt

client = pyuda.Client()  #get the pyuda client


class EFit:
    def __init__(self, shot_number, time, load_mast=True):

        self.shot_number = shot_number
        self.time = time

        self.Bphi_Rgeom = None
        self.Bphi_Rmag = None
        self.Bvac_R = None
        self.Bvac_Rgeom = None
        self.Bvac_Rmag = None
        self.Bvac_val = None

        self.chisq_magnetic = None
        self.chisq_total = None