Source code for tofu.plugins.AUG.SXR.geom._core

# -*- coding: utf-8 -*-
"""
Provides the basic ToFu geometry handling for the SXR diagnostic of AUG
"""



import itertools as itt
import os
import numpy as np
import math
import datetime as dtm
import warnings


# ToFu specific
import tofu.defaults as tfd
import tofu.pathfile as tfpf
import tofu.helper as tfh
import tofu.geom as tfg
from ... import Ves as tfaugVes
from ... import _path as _tfaug_path
from .. import _helper as tfaugSXRh


# AUG specific
import dd

__author__ =    "D. Vezinet"
__all__ = ["create","load","get_GeomFromShot"]


_addpath = '/tofu/plugins/AUG/SXR/geom'


#########################################################
#########################################################
### Storing changes in geometry in a dictionary #########
#########################################################


def _compareDictChan(Dict1, Dict2):
    Crit = ['FiltThick','RPINHOLE','ZPINHOLE','REND','ZEND','Tor_Pos','CAMANGLE','P_Length','P_Width','Foc_Len','D_Length','D_Width','D_Gap','MULTIA02']
    Lim = [5.e-6, 0.5e-3, 0.5e-3, 0.5e-3, 0.5e-3, 0.5, 0.5, 0.1, 0.01, 0.1, 0.1, 0.01, 0.001, 1.e6]
    CritCh = []
    Change = {}

    Names1 = sorted(Dict1.keys())
    Names2 = sorted(Dict2.keys())
    Names = sorted(list(set(Names1+Names2)))

    for nn in Names:
        Change[nn] = {}

        if not nn in Names1:
            Change[nn] = Dict2[nn]

        elif not nn in Names2:
            Change[nn] = Dict1[nn]

        else:
            for ii in range(0,len(Crit)):
                diff = math.fabs(float(Dict1[nn][Crit[ii]]-Dict2[nn][Crit[ii]]))
                if diff > Lim[ii]:
                    Change[nn][Crit[ii]] = diff

        if len(Change[nn].keys())==0:
            del Change[nn]

    return Change



def _get_GeomFromShot_CSX(shot, Nums, CamH, Chan='CamHeads', Verb=True):
    assert Chan in ['All','CamHeads'] or (type(Chan) is list and all([type(cc) is str for cc in Chan])), "Arg Chan must be in ['All','CamHeads'] or a list of channel names !"

    DictChan = {}
    sh = dd.shotfile('CSX',shot)

    # Which channels shall be used for the testing
    if Chan=='All':
        Dir = sh.getObjectNames()
    elif Chan=='CamHeads':  # One per camera head
        Dir = ['CF_020','CG_020','CH_020','CH_052','CH_087','CI_016','CI_052','CI_091','CJ_017','CJ_052','CJ_087','CK_020','CK_055','CL_020','CM_020']
    else:   # Custom
        for ii in range(0,len(Chan)):
            if not Chan[ii][0]=='C':
                Chan[ii] = 'C'+Chan[ii]
        Dir = Chan
    Dir = [Dir[ii] for ii in range(0,len(Dir)) if all([ss in Dir[ii] for ss in ['C','_']]) and all([nn in Nums for nn in Dir[ii][-3:]])]

    # Do the testing
    LNames = []
    for ii in range(0,len(Dir)):
        try:
            Name = Dir[ii][1:]
            load = sh('C'+Name)
            Diag = str(load['SX_DIAG'].data[0]+load['SX_DIAG'].data[1]+load['SX_DIAG'].data[2])
            if not Diag=='000' and Name in CamH.keys():
                tfaugSXRh._get_DictChanFromload(DictChan, Name, load, CamH, Diag)
                if Verb:
                    print("        Done for "+Name)
        except Exception:
            pass
    sh.close()
    return DictChan


def _get_GeomFromShot_CSXscan( Lshots=range(22000,40000,1), Chan='CamHeads', Verb=True ):

    CamH = tfaugSXRh._CamHeads()

    DictShot = {}
    DictChan0 = {}
    DictChan1 = {}
    init = True
    Nums = map(str,range(0,10))
    Change = {}

    Inshots = [True for ss in Lshots]
    for ii in range(0,len(Lshots)):
        shot = int(Lshots[ii])
        success = False
        while not success:
            try:
                if init:
                    DictChan0 = _get_GeomFromShot_CSX(shot, Nums, CamH, Chan=Chan, Verb=Verb)
                    init = False
                    if Verb:
                        print("")
                        print("    Initiated with shot {0}".format(shot))
                    minshot = int(shot)
                    Lshots[ii] = int(shot)
                elif shot>minshot:
                    DictChan1 = _get_GeomFromShot_CSX(shot, Nums, CamH, Chan=Chan, Verb=Verb)
                    change = _compareDictChan(DictChan0, DictChan1)
                    if len(change.keys())>0:
                        Change[shot] = change
                        DictChan0 = dict(DictChan1)
                        if Verb:
                            print("    Change detected for shot {0}".format(shot))
                    minshot = int(shot)
                    Lshots[ii] = int(shot)
                else:
                    Inshots[ii] = False
                success = True
            except Exception:
                if ii==len(Lshots)-1:
                    shot = shot-1
                else:
                    shot = shot+1
    Lshots = [Lshots[ii] for ii in range(0,len(Lshots)) if Inshots[ii]]
    return Change, Lshots



def get_GeomFromShot( shot_init=22006, shot_end=33730, Ds=1000, Chan='CamHeads', Verb=True, save=True ):
    """ Scan the database using diagnostic 'CSX' to identify the shots where changes were made to the SXR diagnostic

    The geometry of a diagnostic changes from year to year due to improvements, adjustments...
    It is necessary to know from which shot a new geometry is valid.
    This function uses the 'CSX' data to scan the stored geometry (and other parameters) of all channels of the SXR diagnostic on a large span of shots to identify the first shots presenting changes.
    Beware... it is long (typically several hours for a scann of all channels on a span of several thousands of shots).

    Parameters
    ----------
    shot_init :     int
        The first shot of the interval to be scanned
    shot_end :      int
        The last shot of the interval to be scanned
    Ds :            10*int
        The step by which the shot numbers will be increased for scanning (initial value, an algorithm then reduces it by dividing by 10 successively to focus on the identified changes)
    Verb :          bool
        Flag indicating whether some extra comments should be printed
    save :          bool
        Flag indicating whether the result should be saved

    Returns
    -------
    Change :        dict
        A dictionary of changes, where the keys are the shot numbers identified as first to change and where the values are themselves dictionaries of the changes implemented
    Array :        np.ndarray
        (2,N) np.ndarray where the first line is the list of shots tested in the last iteration and the second line is 0 or 1 (1 if changes are observed between the corresponding shot and its predecessor)

    """

    Lshots = sorted(list(set(range(shot_init, shot_end+1, Ds)+[shot_end])))
    ds = int(Ds)
    while not ds<1:
        if Verb:
            print("")
            print("    In: ", Lshots)
        Change, Lshots = _get_GeomFromShot_CSXscan( Lshots, Chan=Chan, Verb=Verb )
        Lshots = sorted(list(set(Lshots)))
        Lch = Change.keys()

        Array = np.asarray([Lshots, [ii in Lch for ii in Lshots]])
        if Verb:
            print("    Out: ", Array)

        ds = ds/10
        if ds>=1:
            Lshots = sorted(list(set(itt.chain.from_iterable([range(Lshots[ii-1],Lshots[ii]+1,ds)+[Lshots[ii]] for ii in range(1,len(Lshots)) if Array[1,ii]]))))

    if save:
        Chanstr = Chan if type(Chan) is str else 'Custom'
        Name = 'Changes_'+Chanstr+'_shot{0}-{1}_Ds{2}'.format(shot_init,shot_end,Ds)
        np.savez(_tfaug_path._Root+'/tofu/plugins/AUG/SXR/geom/'+Name+'.npz', Change=[Change], Array=Array)

    return Change, Array






#########################################################
#########################################################
### Using the dictionary to determine relevant shots ####
#########################################################



def _get_GeomFromShot_New(shot, chfile='Changes_CamHeads_shot22006-33730_Ds1000.npz', chpath=_tfaug_path._Root):
    """ Return the last reference geometry shot depending on the input shot and on the Change dictionary selected

    Parameters
    ----------
    shot :      int
        Shot for which the user wants to know which geometry to use
    chfile :    str
        Name of the Changes dictionary to be used

    Returns
    -------
    Rshot:      int
        Reference geometry shot corresponding to the input shot

    """

    shot_init = int(chfile[chfile.index('_shot')+5:chfile.index('-')])
    shot_end = int(chfile[chfile.index('-')+1:chfile.index('-')+6])
    assert shot >= shot_init and shot <= shot_end, "Geometry not computed yet !"

    # Loading the Changes dictionary
    Change = np.load(chpath+_addpath+'/'+chfile)['Change'][0]
    lshots = np.unique(Change.keys())
    assert shot >= np.min(lshots) and shot <= np.max(lshots), "Geometry not computed yet (stored shots in Changes) !"
    Rshot = int(np.max(lshots[lshots<=shot]))

    return Rshot


def _get_RectifiedFromShot(shot):
    """ Get the real lower shot number from CSX

    Check whether the desired shot number is available in the database of CSX diagnostic, if not return the first following one which is

    Parameters
    -----------
    shot :      int
        Desired shot number to be checked

    Returns
    -------
    shotbis :   int
        Closest valid shot number

    """
    Done = False
    shotbis = int(shot)
    while not Done:
        try:
            sh = dd.shotfile('CSX',shotbis)
            Done = True
        except Exception:
            shotbis = shotbis + 1
    sh.close()
    return shotbis


def _get_Tiles_FromShot(shot):
    """ Return the list of camera heads that should be affected by view-limiting tiles depending on the shot number

    In theory, the limiting tiles were removed after #31802, but in practice the gap was probably just widened (but how much ?)

    Parameters
    ----------
    shot :  int
        The shot number for which to return the list

    Returns
    -------
    Tiles :     list
        The list of camera heads with limiting tiles

    """
    Tiles = ['F','G']
    if shot<31802:
        Tiles = Tiles + ['L','M']
    return Tiles




# Old, mot used any more (keep for backward compatibility and double checks)
def _get_GeomFromShot(shot):     # Deprecated
    """ Deprecated """
    assert shot>=24190, "Geometry not computed yet !"
    if shot >= 24190 and shot < 24492:     # Lower bound not adjusted to minimum !
        shot, LCamH = 24190, "All"
    elif shot >= 24492 and shot < 25962:
        shot, LCamH = 24492, "All"
    elif shot >= 25962 and shot < 27439:
        shot, LCamH = 25962, "All"
    elif shot >= 27439 and shot < 31802:
        shot, LCamH = 27439, "All"
    elif shot >= 31802:   #Upper bound to be updated !
        shot, LCamH = 31802, ['L','M']
    return shot, LCamH






#########################################################
#########################################################
### Helper routines to find out which cameras have already been created ####
#########################################################







def _listavailCams(Exp='AUG', Diag='SXR', SavePathObj=None, Root=_tfaug_path._Root, shotstr='_sh'):
    """ Return a dictionary listing, for each camera head (keys), the shot numbers for which it was already created

    A GDetect object is created for each camera head, and several versions of it exist depending on the shot number because of geometry changes in time
    This routine tells you, for each camera head, for which shots it was already created

    Parameters
    ----------
    Exp :           str
        The experiment, here always 'AUG'
    Diag :          str
        The diagnostic, here always 'SXR'
    SavePathObj :   None / str
        The path where to look for already created GDetect objects, if None takes default
    Root : str
        The root path to which '/tofu/plugins/AUG/SXR/geom/Objects/' will be appended to build a default path if SavePathObj is None
    shotstr :       str
        The string pattern used to identify the shot number in the file names

    Returns
    -------
    DC :    dict
        The dictionary containing all relevant info

    """

    if SavePathObj is None:
        SavePathObj = Root + _addpath+ '/Objects/'

    kstr = 'TFG_GDetect_'+Exp+'_Dg'+Diag+'_'
    LC = os.listdir(SavePathObj)
    LC = [cc for cc in LC if all([ss in cc for ss in [kstr,shotstr,'.npz']])]
    DC = {}
    for ii in range(0,len(LC)):
        ind = LC[ii].index(shotstr)
        shot = int(LC[ii][ind+len(shotstr):ind+len(shotstr)+5])
        ind = LC[ii].index(kstr)
        strtemp = LC[ii][ind+len(kstr):]
        indbis = strtemp.index('_')
        CamH = strtemp[:indbis]
        if not CamH in DC.keys():
            DC[CamH] = []
        DC[CamH].append(shot)

    return DC







#########################################################
#########################################################
######## Create cameras (apertures + detectors) #########
#########################################################


def _getLApert( Dict, dd, Ves, shot, SavePathObj, dtime, dtFormat, Exp='AUG', Tiles=['F','G','L','M']):
    """ Return the list of apertures associated to a specific SXR channel

    In AUG, each camera head is associated to a single aperture (data stored in CSX)
    However, for some camera heads, a fraction of the VOS might be obstructed by

    Parameters
    ----------
    Dict :          dict
        Dictionary with all info from CSX, issued by :meth:`~tofu.plugins.AUG.SXR._helper._WhichSX()`
    dd :            str
        Key to Dict, should be a channel name
    Ves :           :class:`tofu.geom.Ves`
        The Ves instance with which to build the Apert objects
    shot :          int
        The shot number with which to build the Apert objects
    SavePathObj :   None / str
        The SavePath where the Apert objects should be saved (None recommended for default)
    dtime :         dtm.datetime
        A dtm.datetime object for identifying the create Apert objects (mostly for debugging)
    dtFormat :      str
        A str flag indicating the format with which dtime should be written in the automatically generated SaveName (if necessary)
    Exp :           str
        The experiment flag on which the Apert objects are created, should be the same as for Ves
    Tiles :      bool
        Flag indicating the list of caamera heads for which an additional aperture should be built from tiles (can be de-activated simply by removing the concerned camera head from the list)

    Returns
    ------
    LApert :        list
        List of apertures, created using the data available in CSX via Dict

    """

    A = np.array([Dict[dd]['RPINHOLE'], Dict[dd]['ZPINHOLE']])
    B = np.array([Dict[dd]['REND'], Dict[dd]['ZEND']])
    phi = Dict[dd]['Tor_Pos']*np.pi/180.
    theta = Dict[dd]['CAMANGLE']*np.pi/180.

    PolyApert, M = tfh.PolyFromLine(A, B, A, theta, phi, float(Dict[dd]['P_Length']*1.e-3), float(Dict[dd]['P_Width']*1.e-3))
    assert np.hypot(np.hypot(M[0],M[1])-A[0], M[2]-A[1]) < 1.e-10, "Something wrong with Apert poly !"
    IdApert0 = tfpf.ID('Apert', Dict[dd]['CamHead'], shot=shot, Diag='SXR', SaveName=None, SavePath=SavePathObj, dtime=dtime, Exp=Exp, LObj=None, dtFormat=dtFormat,
                       USRdict={'Cam':Dict[dd]['Cam'], 'CamHead':Dict[dd]['CamHead'], 'FiltMat':Dict[dd]['FiltMat'], 'FiltThick':Dict[dd]['FiltThick']})
    Apert0 = tfg.Apert(IdApert0, PolyApert, Ves=Ves)
    LApert, LIdApert = [Apert0], [IdApert0]

    # Add extra apertures (space between tiles) for the relevant cameras
    if Dict[dd]['CamHead'] in Tiles:
        if Dict[dd]['Cam']=='F':
            d = 0.034
            LTor, L2 = 0.012, 0.12
            Ang = -(np.pi/2-theta)
        elif Dict[dd]['Cam']=='G':
            d = 0.034
            LTor, L2 = 0.0117, 0.12
            Ang = -(np.pi/2-theta)
        elif Dict[dd]['Cam']=='L':
            d  = 0.040
            LTor, L2 = 0.0064, 0.2
            Ang = -36.9*np.pi/180.
        else:
            d  = 0.036
            LTor, L2 = 0.0054, 0.15
            Ang = 16.75*np.pi/180.
        C = tfh.RZ2XYZ_1D(A,phi) + d*Apert0.nIn
        e2 = np.cross(np.array([-np.sin(phi),np.cos(phi),0]),Apert0.nIn)
        e2 = e2/np.linalg.norm(e2)
        nP = Apert0.nIn*np.cos(Ang) + e2*np.sin(Ang)
        PolyApert = tfh.RectFromPlaneCenter(C, nP, np.array([-np.sin(phi),np.cos(phi),0]), LTor, L2, Test=True)
        LIdApert.append(tfpf.ID('Apert', Dict[dd]['CamHead']+"_Tiles", shot=shot, Diag='SXR', SaveName=None, SavePath=SavePathObj, dtime=dtime, Exp=Exp, LObj=None, dtFormat=dtFormat,
                                USRdict={'Cam':Dict[dd]['Cam'],'CamHead':Dict[dd]['CamHead'],'FiltMat':None,'FiltThick':None}))
        Apert1 = tfg.Apert(LIdApert[-1], PolyApert, Ves=Ves)
        LApert.append(Apert1)
    return LApert




[docs]def create(shot=0, VesName='V1', SavePathObj=None, Root=_tfaug_path._Root, forceshot=False, overwrite=False, save=True, dtime=None, dtFormat=tfd.dtmFormat, CalcEtend=True, CalcSpanImp=True, CalcCone=True, CalcPreComp=True, Calc=True, Verb=True, Etend_Method='quad', Etend_RelErr=1.e-3, Etend_dX12=[0.01,0.01], Etend_dX12Mode='rel', Etend_Ratio=0.02, Colis=True, LOSRef='Cart', Cone_DRY=0.0025, Cone_DXTheta=np.pi/1024., Cone_DZ=0.0025, Cone_NPsi=20, Cone_Nk=60): """ Create, save and return all the GDetect objects relevant for the input shot, unless already created for a relevant reference shot Create the :class:`tofu.geom.GDetect` objects (i.e.: the cameras, which are groups of detectors) from geometry taken from CSX disgnostic for the proposed shot or earlier (looks for the oldest version of the matching geometry) and stores them in the SavePathObj. All extra arguments are fed to :class:`~tofu.geom.Detect` Parameters ---------- shot : int Shot number for which to build the geometry VesName : str Name of the tfg.Ves object to be fed as an input to the :class:`tofu.geom.GDetect` objects SavePathObj : None / str Absolute path where the created :class:`tofu.geom.GDetect` objects should be saved (if save=True), if None the default is used Root : str If SavePathObj=None, a default value is created by appending '/tofu/plugins/AUG/SXR/geom/Objects/' to Root forceshot : bool Flag indicating whether the shot number shall be downgraded to the oldest shot with the same geometry (False) or whether the provided shot number shall be enforced (True, for all camera heads) overwrite : bool Flag indicating whether new :class:`tofu.geom.GDetect` objects shall be computed (and possibly saved) when similar ones already exist (True) save : bool Flag indicating whether to save the created :class:`tofu.geom.GDetect` objects (in SavePathObj) dtime : None / dtm.datetime If provided (i.e.: not None), used as a label of the created :class:`tofu.geom.GDetect` objects (mostly used for debugging) dtFormat : str The time format to be used for labelling the created :class:`tofu.geom.GDetect` objects (mostly used for debugging) Returns ------- LGD : list A list of all the created tfg.GDetect objects """ # Pre-formatting inputs if SavePathObj is None: SavePathObj = Root + _addpath + '/Objects/' # LMNoTile = _get_LMTilesFromShot(shot) # Deprecated, replace by proper scanning / refit of several successive shots if not forceshot: #shot, LCamH = _get_GeomFromShot(shot) shot = _get_GeomFromShot_New(shot) #else: # LCamH = "All" #if not LCamH=="All": # assert LCamH in CamHeads or all([cc in CamHeads for cc in LCamH]) #else: # LCamH = CamHeads shot = _get_RectifiedFromShot(shot) Dict = tfaugSXRh._WhichSX(shot=shot) Ves = tfaugVes.load(VesName) Tiles = _get_Tiles_FromShot(shot) # Computing and saving UnCamH = sorted(list(set([Dict[dd]['CamHead'] for dd in Dict.keys()]))) ListGDPre = _listavailCams(Exp='AUG', Diag='SXR', SavePathObj=SavePathObj, Root=Root, shotstr='_sh') LGD = [] for ii in range(0,len(UnCamH)): cond0 = overwrite cond1 = not UnCamH[ii] in ListGDPre.keys() or not shot in ListGDPre[UnCamH[ii]] if any([cond0, cond1]): lds = sorted([dd for dd in Dict.keys() if Dict[dd]['CamHead']==UnCamH[ii]]) LApert = _getLApert(Dict, lds[0], Ves, shot, SavePathObj, dtime, dtFormat, Tiles=Tiles, Exp='AUG') LD = [] for dd in lds: Id = tfpf.ID('Detect', dd, shot=shot, Diag='SXR', SaveName=None, SavePath=SavePathObj, dtime=dtime, Exp='AUG', LObj=None, dtFormat=dtFormat, USRdict={'Cam':Dict[dd]['Cam'], 'CamHead':Dict[dd]['CamHead'], 'Diag':Dict[dd]['Diag'], 'Sig':Dict[dd]['Sig'], 'Num':Dict[dd]['Num'], 'FiltMat':Dict[dd]['FiltMat'], 'FiltThick':Dict[dd]['FiltThick'], 'Sampl':Dict[dd]['Sampling'], 'Address':Dict[dd]['Address']}) A = np.array([Dict[dd]['RPINHOLE'], Dict[dd]['ZPINHOLE']]) B = np.array([Dict[dd]['REND'], Dict[dd]['ZEND']]) phi = Dict[dd]['Tor_Pos']*np.pi/180. theta = Dict[dd]['CAMANGLE']*np.pi/180. RIn = np.hypot(LApert[0].BaryS[0]+LApert[0].nIn[0],LApert[0].BaryS[1]+LApert[0].nIn[1]) - np.hypot(LApert[0].BaryS[0],LApert[0].BaryS[1]) Sgn = np.sign(RIn*np.cos(theta) + LApert[0].nIn[2]*np.sin(theta)) P = A - Sgn*1.e-3*Dict[dd]['Foc_Len']*np.array([np.cos(theta), np.sin(theta)]) DTor, DPol, DGap = float(1.e-3*Dict[dd]['D_Length']), float(1.e-3*Dict[dd]['D_Width']), float(1.e-3*Dict[dd]['D_Gap']) Poly, M = tfh.PolyFromLine(A, B, P, theta, phi, DTor, DPol) DD = np.hypot(np.hypot(M[0],M[1])-P[0], M[2]-P[1]) nn = DD/(DGap+DPol) assert np.abs(nn-np.round(nn))<0.017, "Inconsistent location of center for "+dd+", abs(nn-round(nn)) = "+str(np.abs(nn-np.round(nn)))+" with nn = "+str(nn) Det = tfg.Detect(Id, Poly, Optics=LApert, Ves=Ves, Sino_RefPt=None, CalcEtend=CalcEtend, CalcSpanImp=CalcSpanImp, CalcCone=CalcCone, CalcPreComp=CalcPreComp, Calc=Calc, Verb=Verb, Etend_Method=Etend_Method, Etend_RelErr=Etend_RelErr, Etend_dX12=Etend_dX12, Etend_dX12Mode=Etend_dX12Mode, Etend_Ratio=Etend_Ratio, Colis=Colis, LOSRef=LOSRef, Cone_DRY=Cone_DRY, Cone_DXTheta=Cone_DXTheta, Cone_DZ=Cone_DZ, Cone_NPsi=Cone_NPsi, Cone_Nk=Cone_Nk, arrayorder='C', Clock=False, Type=None, Exp='AUG', Diag='SXR', shot=shot, dtime=None, dtimeIn=False, SavePath=SavePathObj) LD.append(Det) GD = tfg.GDetect(UnCamH[ii], LDetect=LD, Type=None, Exp='AUG', Diag='SXR', shot=shot, Sino_RefPt=None, LOSRef='Cart', arrayorder='C', Clock=False, dtime=None, dtimeIn=False, SavePath=SavePathObj) if save: GD.save(SynthDiag=True) LGD.append(GD) return LGD
######################################################### ######################################################### ############ Loading tools ############################## #########################################################
[docs]def load(Cams=None, shot=None, SavePathObj=None, Root=_tfaug_path._Root, sort=False, out='full', Test=True): """ Load and return the desired :class:`~tofu.geom.GDetect` objects (i.e.: camera heads) Directly fecthes and loads the desired :class:`~tofu.geom.GDetect` objects. Parameters ---------- Cams : str / list A name or a list of names of the camera heads to be loaded (available are ['F','G','H1','H2','H3','I1','I2','I3','J1','J2','J3','K1','K2','L','M']) shot : int / float / np.float A shot number indicating which version of the geometry should be loaded (the ) SavePathObj : None / str Absolute path where the created :class:`tofu.geom.GDetect` objects should be saved (if save=True), if None the default is used Root : str If SavePathObj=None, a default value is created by appending '/tofu/plugins/AUG/SXR/geom/Objects/' to Root sort : bool Flag indicating whether the loaded :class:`tofu.geom.GDetect` objects shall be returned sorted by alphabetical order of the names (True) or in the same order as asked in Cams (False) out : str Flag indicating whether the object should be loaded completely ('full'), in a light dismissing the heaviest attributes ('light') or whether only the Id or a list of Id should be returned ('Id'), valid only for '.npz' Test : bool Flag indicating whether the inputs should be tested for conformity Returns: -------- LGD : list / :class:`tofu.geom.GDetect` The loaded :class:`tofu.geom.GDetect`, returned as a single object if Cams was provided as a single name, as a list otherwise """ if Test: assert Cams is None or type(Cams) is str or (type(Cams) is list and all([type(cc) is str for cc in Cams])), "Arg Cams must be a str or a list of such !" assert shot is None or type(shot) in [int,float,np.float], "Arg shot must be a int !" # Pre-formatting inputs Flagstr = False if type(Cams) is str: Cams = [Cams] Flagstr = True if SavePathObj is None: SavePathObj = Root + _addpath + '/Objects/' # List available cameras heads, sort and select the relevant files DC = _listavailCams(Exp='AUG', Diag='SXR', SavePathObj=SavePathObj, Root=Root, shotstr='_sh') Cams = sorted(DC.keys()) if Cams is None else Cams assert all([cc in DC.keys() for cc in Cams]), "Some Cams asked for are not available in "+SavePathObj Cams = sorted(Cams) if sort else Cams # Loading LGD = [] for ii in range(0,len(Cams)): sh = DC[Cams[ii]] if shot is None else [sh for sh in DC[Cams[ii]] if sh<shot] if len(sh)==0: warnings.warn(" Camera "+Cams[ii]+" could not be loaded because it was only computed for later shots !") else: sh = max(sh) ff = 'TFG_GDetect_AUG_DgSXR_'+Cams[ii]+'_sh'+str(sh)+'.npz' gd = tfpf.Open(SavePathObj + ff, out=out) LGD.append( gd ) if len(LGD)>0: LGD = LGD[0] if Flagstr else LGD return LGD