Exemple #1
0
def readVoxet(domain,
              filename,
              voproperty=1,
              origin=None,
              fillValue=0.,
              referenceSystem=CartesianReferenceSystem()):
    """
    Reads a single property from a GOCAD Voxet file and returns a data
    object on the given domain with the property data.
    Restrictions:
    - Voxet origin in UVW space (i.e. AXIS_MIN) needs to be [0,0,0]
    - samples size must be 4 (float32) or 8 (float64)
    - data type must be IEEE
    - format must be RAW
    - domain resolution must be (approximately) a multiple of voxet resolution

    :param domain: the domain to use for data (must be a ripley domain)
    :type domain: `Domain`
    :param filename: Voxet header filename (usually ends in .vo)
    :type filename: ``string``
    :param voproperty: identifier of the property to read. Either the numeric
                       property ID, the property name, or the filename of the
                       property data.
    :type voproperty: ``int`` or ``string``
    :param origin: if supplied will override the Voxet origin as read from the
                   file.
    :type origin: ``list`` or ``tuple`` or ``None``
    :param fillValue: value to use for cells that are not covered by property
                      data (if applicable)
    :type fillValue: ``float``
    :param referenceSystem: coordinate system of domain. Used to scale vertical
                            axis accordingly
    :type referenceSystem: `ReferenceSystem`
    """
    from esys.ripley import readBinaryGrid, BYTEORDER_BIG_ENDIAN, DATATYPE_FLOAT32, DATATYPE_FLOAT64
    header = open(filename).readlines()
    if not header[0].startswith('GOCAD Voxet'):
        raise ValueError("Voxet header not found. Invalid Voxet file?!")
    NE = None
    axis_uvw = [None, None, None]
    axis_min = [0., 0., 0.]
    axis_max = [1., 1., 1.]
    # props[id]=[name,file,datatype]
    props = {}
    for line in header:
        if line.startswith('AXIS_O '):
            if origin is None:
                origin = [float(i) for i in line.split()[1:4]]
        elif line.startswith('AXIS_U '):
            u = [float(i) for i in line.split()[1:4]]
            if (u[1] != 0) or (u[2] != 0):
                raise ValueError('This coordinate system is not supported')
            axis_uvw[0] = u[0]
        elif line.startswith('AXIS_V '):
            v = [float(i) for i in line.split()[1:4]]
            if (v[0] != 0) or (v[2] != 0):
                raise ValueError('This coordinate system is not supported')
            axis_uvw[1] = v[1]
        elif line.startswith('AXIS_W '):
            w = [float(i) for i in line.split()[1:4]]
            if (w[0] != 0) or (w[1] != 0):
                raise ValueError('This coordinate system is not supported')
            axis_uvw[2] = w[2]
        elif line.startswith('AXIS_MIN '):
            axis_min = [float(i) for i in line.split()[1:4]]
            if axis_min != [0, 0, 0]:
                raise ValueError('AXIS_MIN != [0,0,0] is not supported')
        elif line.startswith('AXIS_MAX '):
            axis_max = [float(i) for i in line.split()[1:4]]
        elif line.startswith('AXIS_N '):
            NE = [int(i) for i in line.split()[1:4]]
        elif line.startswith('PROPERTY '):
            propid = int(line.split()[1])
            if not propid in props:
                props[propid] = [None, None, None]
            props[propid][0] = line.split()[2].strip()
        elif line.startswith('PROP_ESIZE '):
            propid = int(line.split()[1])
            t = int(line.split()[2])
            if t == 4:
                props[propid][2] = DATATYPE_FLOAT32
            elif t == 8:
                props[propid][2] = DATATYPE_FLOAT64
            else:
                raise ValueError('Unsupported data size ' + t)
        elif line.startswith('PROP_ETYPE '):
            t = line.split()[2].strip()
            if t != 'IEEE':
                raise ValueError('Unsupported data type ' + t)
        elif line.startswith('PROP_FORMAT '):
            t = line.split()[2].strip()
            if t != 'RAW':
                raise ValueError('Unsupported data format ' + t)
        elif line.startswith('PROP_OFFSET '):
            dataoffset = int(line.split()[2])
            if dataoffset != 0:
                raise ValueError('data offset != 0 not supported')
        elif line.startswith('PROP_FILE '):
            propid = int(line.split()[1])
            props[propid][1] = line.split()[2].strip()

    if (axis_uvw[0] is None) or (axis_uvw[1] is None) or (axis_uvw[2] is None)\
            or (NE is None) or (origin is None):
        raise ValueError(
            'Could not determine data configuration. Invalid file?!')
    if len(props) == 0:
        raise ValueError('No properties found.')

    # voxets have these conventions:
    # AXIS_N = number of samples (=cells!) in each dimension
    # AXIS_UVW * AXIS_MAX = voxet length in each dimension
    # AXIS_O = origin of voxet (cell centres!)
    # see also http://paulbourke.net/dataformats/gocad/gocad.pdf

    length = [axis_uvw[i] * axis_max[i] for i in range(3)]

    # modify length and origin to account for the fact that Voxet cells are
    # centred at the data points, i.e.:
    # BEFORE:                   AFTER:
    #
    #       O----length---->|        O------length------>|
    #      ___________________        ___________________
    #     | * | * | * | * | * |      | * | * | * | * | * |
    #      -------------------        -------------------

    for i in range(3):
        dz = length[i] / (NE[i] - 1)
        origin[i] -= dz / 2.
        length[i] += dz

    if referenceSystem.isCartesian():
        v_scale = 1.
    else:
        v_scale = 1. / referenceSystem.getHeightUnit()

    origin[-1] = origin[-1] * v_scale

    # retrieve domain configuration so we know where to place the voxet data
    gridorigin, gridspacing, gridNE = domain.getGridParameters()

    # determine base location of this dataset within the domain
    first = [
        int((origin[i] - gridorigin[i]) / gridspacing[i])
        for i in range(domain.getDim())
    ]

    # determine the resolution difference between domain and data.
    # If domain has twice the resolution we can double up the data etc.
    multiplier = [
        int(round((abs(length[i]) / NE[i]) / gridspacing[i]))
        for i in range(domain.getDim())
    ]

    # NOTE: Depending on your data you might have to multiply your vertical
    # multiplier by 1000. to convert km in meters.
    #multiplier[-1] = int(multiplier[-1] * v_scale * 1000.)
    multiplier[-1] = int(multiplier[-1] * v_scale)

    datatype = None
    propfile = None
    for pid in props.keys():
        p = props[pid]
        if (isinstance(voproperty, int) and pid == voproperty) or \
           (isinstance(voproperty, str) and (p[0]==voproperty or p[1]==voproperty)):
            datatype = p[2]
            name = p[1]
            #remove quotes which GoCAD introduces for filenames with spaces
            if name.startswith('"') and name.endswith('"'):
                name = name[1:-1]
            propfile = os.path.join(os.path.dirname(filename), name)
            print("Voxet property file: %s" % propfile)
            break

    if propfile is None or datatype is None:
        raise ValueError("Invalid property " + str(voproperty))

    reverse = [0] * domain.getDim()
    if axis_uvw[-1] < 0:
        reverse[-1] = 1

    print(
        "calling readBinaryGrid with first=%s, nValues=%s, multiplier=%s, reverse=%s"
        % (str(first), str(NE), str(multiplier), str(reverse)))
    data = readBinaryGrid(propfile,
                          ReducedFunction(domain),
                          shape=(),
                          fill=fillValue,
                          byteOrder=BYTEORDER_BIG_ENDIAN,
                          dataType=p[2],
                          first=first,
                          numValues=NE,
                          multiplier=multiplier,
                          reverse=reverse)

    return data
def readVoxet(domain, filename, voproperty=0, origin=None, fillValue=0.,
              reference_system=None):
    """This subroutine reads in the Voxet and returns an escript Data object"""
    header=open(filename).readlines()
    if not header[0].startswith('GOCAD Voxet'):
        raise ValueError("Invalid Voxet file")
    NE=None
    axis_uvw=[None,None,None]
    axis_min=[0.,0.,0.]
    axis_max=[1.,1.,1.]
    # props[id]=[name,file,datatype]
    props={}
    for line in header:
        if line.startswith('AXIS_O '):
            if origin is None:
                origin=[float(i) for i in line.split()[1:4]]
        elif line.startswith('AXIS_U '):
            u=[float(i) for i in line.split()[1:4]]
            if (u[1] != 0) or (u[2] != 0):
                raise ValueError('This coordinate system is not supported')
            axis_uvw[0]=u[0]
        elif line.startswith('AXIS_V '):
            v=[float(i) for i in line.split()[1:4]]
            if (v[0] != 0) or (v[2] != 0):
                raise ValueError('This coordinate system is not supported')
            axis_uvw[1]=v[1]
        elif line.startswith('AXIS_W '):
            w=[float(i) for i in line.split()[1:4]]
            if (w[0] != 0) or (w[1] != 0):
                raise ValueError('This coordinate system is not supported')
            axis_uvw[2]=w[2]
        elif line.startswith('AXIS_MIN '):
            axis_min=[float(i) for i in line.split()[1:4]]
        elif line.startswith('AXIS_MAX '):
            axis_max=[float(i) for i in line.split()[1:4]]
        elif line.startswith('AXIS_N '):
            NE=[int(i) for i in line.split()[1:4]]
        elif line.startswith('PROPERTY '):
            propid=int(line.split()[1])
            if not props.has_key(propid):
                props[propid]=[None,None,None]
            props[propid][0]=line.split()[2].strip()
        elif line.startswith('PROP_ESIZE '):
            propid=int(line.split()[1])
            t=int(line.split()[2])
            if t==4:
                props[propid][2]=DATATYPE_FLOAT32
            elif t==8:
                props[propid][2]=DATATYPE_FLOAT64
            else:
                raise ValueError('Unsupported data size '+t)
        elif line.startswith('PROP_ETYPE '):
            t=line.split()[2].strip()
            if t != 'IEEE':
                raise ValueError('Unsupported data type '+t)
        elif line.startswith('PROP_FORMAT '):
            t=line.split()[2].strip()
            if t != 'RAW':
                raise ValueError('Unsupported data format '+t)
        elif line.startswith('PROP_OFFSET '):
            dataoffset=int(line.split()[2])
            if dataoffset != 0:
                raise ValueError('data offset != 0 not supported yet')
        elif line.startswith('PROP_FILE '):
            propid=int(line.split()[1])
            props[propid][1]=line.split()[2].strip()

    if (axis_uvw[0] is None) or (axis_uvw[1] is None) or (axis_uvw[2] is None)\
            or (NE is None) or (origin is None):
        raise ValueError('Could not determine data configuration. Invalid file?!')
    if len(props)==0:
        raise ValueError('No properties found.')

    #l=[(origin[i], origin[i]+axis_uvw[i]*axis_max[i]) for i in range(3)]
    gridorigin, gridspacing, gridNE = domain.getGridParameters()
    if not reference_system:
         reference_system = CartesianReferenceSystem()

    if reference_system.isCartesian():
        v_scale=1.
    else:
        v_scale=1./reference_system.getHeightUnit()

    # add 2x half cells (top and bottom)
    dz = axis_uvw[-1] / (NE[-1]-1)
    axis_uvw = [x + dz for x in axis_uvw]
    origin[-1] = origin[-1]*v_scale

    # determine base location of this dataset within the domain
    first=[int((origin[i]-gridorigin[i])/gridspacing[i]) for i in range(domain.getDim())]

    datatype=None
    propfile=None
    for p in props.values():
        if (isinstance(voproperty, int) and p[1] == voproperty) or \
           (isinstance(voproperty, str) and p[0] == voproperty):
            datatype=p[2]
            name=p[1]
            # remove quotes which GoCAD introduces for filenames with spaces
            if name.startswith('"') and name.endswith('"'):
                name=name[1:-1]
            propfile=os.path.join(os.path.dirname(filename), name)
            print("Voxet property file: %s"%propfile)
            break

    if propfile is None or datatype is None:
        raise ValueError("Invalid property "+str(voproperty))

    multiplier = [1,1,1]
    reverse = [0]*domain.getDim()
    if axis_uvw[-1] < 0:
        reverse[-1]=1

    data=readBinaryGrid(propfile, ReducedFunction(domain), shape=(),
            fill=fillValue, byteOrder=BYTEORDER_BIG_ENDIAN,
            dataType=p[2], first=first, numValues=NE, multiplier=multiplier,
            reverse=reverse)
    return data
def RegionalCalculation(reg_mask):
    """
    Calculates the "regional" from the entire FEILDS model excluding the
    selected region and outputs gravity at the specified altitude...
    see above for the "residual"
    """

    # read in a gravity data grid to define data computation space
    G_DATA = os.path.join(DATADIR,'Final_BouguerTC_UC15K_qrtdeg.nc')
    FS=ReducedFunction(dom)
    nValues=[NX, NY, 1]
    first = [0, 0, cell_at_altitude]
    multiplier = [1, 1, 1]
    reverse = [0, 0, 0]
    byteorder = BYTEORDER_NATIVE
    gdata = readBinaryGrid(G_DATA, FS, shape=(),
                fill=-999999, byteOrder=byteorder,
                dataType=DATATYPE_FLOAT32, first=first, numValues=nValues,
                multiplier=multiplier, reverse=reverse)
    print("Grid successfully read")

    # get the masking and units sorted out for the data-space
    g_mask = whereNonZero(gdata+999999)

    gdata=gdata*g_mask * GRAV_UNITS

    # if people choose to have air in their region we exclude it from the
    # specified gravity calculation region
    if h_top < 0.:
        reg_mask = reg_mask+mask_air

    live_model = initial_model* whereNonPositive(reg_mask)
    dead_model = initial_model* wherePositive(reg_mask)

    if UseMean is True:
        # calculate the mean density within the selected region
        BackgroundDensity = integrate(dead_model)/integrate(wherePositive(reg_mask))
        print("Density mean for selected region equals = %s"%BackgroundDensity)

        live_model = live_model + BackgroundDensity * wherePositive(reg_mask)

    # create mapping
    rho_mapping = DensityMapping(dom, rho0=live_model)

    # invert sign of gravity field to account for escript's coordinate system
    gdata = -GRAV_UNITS * gdata

    # turn the scalars into vectors (vertical direction)
    d=kronecker(DIM)[DIM-1]
    w=safeDiv(1., g_mask)
    gravity_model=GravityModel(dom, w*d, gdata*d, fixPotentialAtBottom=False, coordinates=COORDINATES)
    gravity_model.rescaleWeights(rho_scale=rho_mapping.getTypicalDerivative())
    phi,_ = gravity_model.getArguments(live_model)
    g_init = -gravity_model.getCoordinateTransformation().getGradient(phi)
    g_init = interpolate(g_init, gdata.getFunctionSpace())
    print("Computed gravity: %s"%(g_init[2]))

    fn=os.path.join(OUTPUTDIR,'regional-gravity')
    if SiloOutput is True:
        saveSilo(fn, density=live_model, gravity_init=g_init, g_initz=-g_init[2], gravitymask=g_mask, modelmask=reg_mask)
        print('SILO file written with the following fields: density (kg/m^3), gravity vector (m/s^2), gz (m/s^2), gravitymask, modelmask')

    # to compare calculated data against input dataset.
    # Not used by default but should work if the input dataset is correct
    #gslice = g_init[2]*wherePositive(g_mask)
    #g_dash = integrate(gslice)/integrate(wherePositive(g_mask))
    #gdataslice = gdata*wherePositive(g_mask)
    #gdata_dash = integrate(gdataslice)/integrate(wherePositive(g_mask))
    #misfit=(gdataslice-gdata_dash)-(gslice-g_dash)
    saveDataCSV(fn+".csv", mask=g_mask, gz=-g_init[2], Long=datacoords[0], Lat=datacoords[1], h=datacoords[2])
    print('CSV file written with the following fields: Longitude (degrees) Latitude (degrees), h (100km), gz (m/s^2)')
Exemple #4
0
def readVoxet(domain, filename, voproperty=1, origin=None, fillValue=0.,
              referenceSystem=CartesianReferenceSystem()):
    """
    Reads a single property from a GOCAD Voxet file and returns a data
    object on the given domain with the property data.
    Restrictions:
    - Voxet origin in UVW space (i.e. AXIS_MIN) needs to be [0,0,0]
    - samples size must be 4 (float32) or 8 (float64)
    - data type must be IEEE
    - format must be RAW
    - domain resolution must be (approximately) a multiple of voxet resolution

    :param domain: the domain to use for data (must be a ripley domain)
    :type domain: `Domain`
    :param filename: Voxet header filename (usually ends in .vo)
    :type filename: ``string``
    :param voproperty: identifier of the property to read. Either the numeric
                       property ID, the property name, or the filename of the
                       property data.
    :type voproperty: ``int`` or ``string``
    :param origin: if supplied will override the Voxet origin as read from the
                   file.
    :type origin: ``list`` or ``tuple`` or ``None``
    :param fillValue: value to use for cells that are not covered by property
                      data (if applicable)
    :type fillValue: ``float``
    :param referenceSystem: coordinate system of domain. Used to scale vertical
                            axis accordingly
    :type referenceSystem: `ReferenceSystem`
    """
    from esys.ripley import readBinaryGrid, BYTEORDER_BIG_ENDIAN, DATATYPE_FLOAT32, DATATYPE_FLOAT64
    header=open(filename).readlines()
    if not header[0].startswith('GOCAD Voxet'):
        raise ValueError("Voxet header not found. Invalid Voxet file?!")
    NE=None
    axis_uvw=[None,None,None]
    axis_min=[0.,0.,0.]
    axis_max=[1.,1.,1.]
    # props[id]=[name,file,datatype]
    props={}
    for line in header:
        if line.startswith('AXIS_O '):
            if origin is None:
                origin=[float(i) for i in line.split()[1:4]]
        elif line.startswith('AXIS_U '):
            u=[float(i) for i in line.split()[1:4]]
            if (u[1] != 0) or (u[2] != 0):
                raise ValueError('This coordinate system is not supported')
            axis_uvw[0]=u[0]
        elif line.startswith('AXIS_V '):
            v=[float(i) for i in line.split()[1:4]]
            if (v[0] != 0) or (v[2] != 0):
                raise ValueError('This coordinate system is not supported')
            axis_uvw[1]=v[1]
        elif line.startswith('AXIS_W '):
            w=[float(i) for i in line.split()[1:4]]
            if (w[0] != 0) or (w[1] != 0):
                raise ValueError('This coordinate system is not supported')
            axis_uvw[2]=w[2]
        elif line.startswith('AXIS_MIN '):
            axis_min=[float(i) for i in line.split()[1:4]]
            if axis_min != [0,0,0]:
                raise ValueError('AXIS_MIN != [0,0,0] is not supported')
        elif line.startswith('AXIS_MAX '):
            axis_max=[float(i) for i in line.split()[1:4]]
        elif line.startswith('AXIS_N '):
            NE=[int(i) for i in line.split()[1:4]]
        elif line.startswith('PROPERTY '):
            propid=int(line.split()[1])
            if not propid in props:
                props[propid]=[None,None,None]
            props[propid][0]=line.split()[2].strip()
        elif line.startswith('PROP_ESIZE '):
            propid=int(line.split()[1])
            t=int(line.split()[2])
            if t==4:
                props[propid][2]=DATATYPE_FLOAT32
            elif t==8:
                props[propid][2]=DATATYPE_FLOAT64
            else:
                raise ValueError('Unsupported data size '+t)
        elif line.startswith('PROP_ETYPE '):
            t=line.split()[2].strip()
            if t != 'IEEE':
                raise ValueError('Unsupported data type '+t)
        elif line.startswith('PROP_FORMAT '):
            t=line.split()[2].strip()
            if t != 'RAW':
                raise ValueError('Unsupported data format '+t)
        elif line.startswith('PROP_OFFSET '):
            dataoffset=int(line.split()[2])
            if dataoffset != 0:
                raise ValueError('data offset != 0 not supported')
        elif line.startswith('PROP_FILE '):
            propid=int(line.split()[1])
            props[propid][1]=line.split()[2].strip()

    if (axis_uvw[0] is None) or (axis_uvw[1] is None) or (axis_uvw[2] is None)\
            or (NE is None) or (origin is None):
        raise ValueError('Could not determine data configuration. Invalid file?!')
    if len(props)==0:
        raise ValueError('No properties found.')

    # voxets have these conventions:
    # AXIS_N = number of samples (=cells!) in each dimension
    # AXIS_UVW * AXIS_MAX = voxet length in each dimension
    # AXIS_O = origin of voxet (cell centres!)
    # see also http://paulbourke.net/dataformats/gocad/gocad.pdf

    length = [axis_uvw[i]*axis_max[i] for i in range(3)]

    # modify length and origin to account for the fact that Voxet cells are
    # centred at the data points, i.e.:
    # BEFORE:                   AFTER:
    #
    #       O----length---->|        O------length------>|
    #      ___________________        ___________________
    #     | * | * | * | * | * |      | * | * | * | * | * |
    #      -------------------        -------------------

    for i in range(3):
        dz = length[i] / (NE[i]-1)
        origin[i] -= dz/2.
        length[i] += dz

    if referenceSystem.isCartesian():
        v_scale=1.
    else:
        v_scale=1./referenceSystem.getHeightUnit()

    origin[-1] = origin[-1]*v_scale

    # retrieve domain configuration so we know where to place the voxet data
    gridorigin, gridspacing, gridNE = domain.getGridParameters()

    # determine base location of this dataset within the domain
    first=[int((origin[i]-gridorigin[i])/gridspacing[i]) for i in range(domain.getDim())]

    # determine the resolution difference between domain and data.
    # If domain has twice the resolution we can double up the data etc.
    multiplier=[int(round((abs(length[i])/NE[i])/gridspacing[i])) for i in range(domain.getDim())]

    # NOTE: Depending on your data you might have to multiply your vertical
    # multiplier by 1000. to convert km in meters.
    #multiplier[-1] = int(multiplier[-1] * v_scale * 1000.)
    multiplier[-1] = int(multiplier[-1] * v_scale)

    datatype=None
    propfile=None
    for pid in props.keys():
        p=props[pid]
        if (isinstance(voproperty, int) and pid == voproperty) or \
           (isinstance(voproperty, str) and (p[0]==voproperty or p[1]==voproperty)):
            datatype=p[2]
            name=p[1]
            #remove quotes which GoCAD introduces for filenames with spaces
            if name.startswith('"') and name.endswith('"'):
                name=name[1:-1]
            propfile=os.path.join(os.path.dirname(filename), name)
            print("Voxet property file: %s"%propfile)
            break

    if propfile is None or datatype is None:
        raise ValueError("Invalid property "+str(voproperty))

    reverse=[0]*domain.getDim()
    if axis_uvw[-1] < 0:
        reverse[-1]=1

    print("calling readBinaryGrid with first=%s, nValues=%s, multiplier=%s, reverse=%s"%(str(first),str(NE),str(multiplier),str(reverse)))
    data=readBinaryGrid(propfile, ReducedFunction(domain), shape=(),
            fill=fillValue, byteOrder=BYTEORDER_BIG_ENDIAN,
            dataType=p[2], first=first, numValues=NE, multiplier=multiplier,
            reverse=reverse)

    return data