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
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()
""" 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()
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
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
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,:]
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
''' 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