[Thread Prev][Thread Next][Index]

Re: [ferret_users] Python externat function with several arguments with different shapes.



Hi Olivier,

You need to describe the grid of the result.

By default Ferret/PyFerret assumes the axes of the results of an external function (in Fortran or Python) is inherited from the axes of all the argument(s).  This means all arguments must have compatible grids and the result will be this grid.  If this is not the case (as in your PyEF), one needs to describe the what axes are inherited from which arguments, and/or if the result uses custom (or abstract) axes.  There is an example under "A grid-changing PyEF" on the documentation page https://ferret.pmel.noaa.gov/Ferret/documentation/pyferret/pyefs  

In your case you could add the following to the initialization dictionary variable "initdict":

        "axes": (pyferret.AXIS_IMPLIED_BY_ARGS, pyferret.AXIS_IMPLIED_BY_ARGS,
                 pyferret.AXIS_IMPLIED_BY_ARGS, pyferret.AXIS_IMPLIED_BY_ARGS,
                 pyferret.AXIS_IMPLIED_BY_ARGS, pyferret.AXIS_IMPLIED_BY_ARGS),
        "influences": ((False,False,False,False,False,False),
                       (True,True,True,True,True,True)),

(The "axes" tuple above is actually the default and only "influences" tuple of tuples is actually needed here, but I include it for the custom axis discussion below.)  
This would tell Ferret to that the grid of the result is exactly the grid of the second argument and the grid of the first argument does not have any effect on the results.  Thus, the grids of the two arguments do not need to be compatible.

If an axis of the grid of the result is actually different from either grid (for example, values are at the midpoints of the "bins" of an axis and has one less value), then you would need to call the axis a custom axis "pyferret.AXIS_CUSTOM" (or possibly an abstract axis "pyferret.AXIS_ABSTRACT"), indicate that neither argument axis influences the result axis, then describe the custom axes by defining the "ferret_custom_axes" method (and/or describe the abstract axes by defining the "ferret_result_limits" method).  The example referenced above has more information on doing this.

Best,
Karl


On Thu, Jan 23, 2020 at 2:54 AM Olivier Marti <olivier.marti@xxxxxxxxxxxx> wrote:
Hello everybody,

I'm trying to build a python external function (PyEF). It should build an histogram from a list of classes. So the input arguments will be a Ferret array, and a list of classes. With a call like :

histo(  SIICECOV[L=1,K=1])         , XSEQUENCE({0., 0.1, 0.2, 1.0, 2.0}) )
or
histo( XSEQUENCE(SIICECOV[L=1,K=1]), XSEQUENCE({0., 0.1, 0.2, 1.0, 2.0}) )
or
histo( XSEQUENCE(SIICECOV[L=1,K=1]), YSEQUENCE({0., 0.1, 0.2, 1.0, 2.0}) )

But it always fails. For instance :

> STAT histo( XSEQUENCE(SIICECOV[L=1,K=1]), XSEQUENCE({0., 0.1, 0.2, 1.0, 2.0}) )
 **ERROR: inconsistent sizes of data regions: X axis
          XSEQUENCE({0., 0.1, 0.2, 1.0, 2.0}) has 5 points (I=1:5)
          _expression_ has 9216 points (I=0001:9216)
STAT histo( XSEQUENCE(SIICECOV[L=1,K=1]), XSEQUENCE({0., 0.1, 0.2, 1.0, 2.0}) )
Command file, command group, or REPEAT execution aborted


or

> STAT histo( XSEQUENCE(SIICECOV[L=1,K=1]), XYEQUENCE({0., 0.1, 0.2, 1.0, 2.0}) )
 **ERROR: command syntax: XYEQUENCE({0., 0.1, 0.2, 1.0, 2.0})
          unknown function "XYEQUENCE"
STAT histo( XSEQUENCE(SIICECOV[L=1,K=1]), XYEQUENCE({0., 0.1, 0.2, 1.0, 2.0}) )
Command file, command group, or REPEAT execution aborted




Before performing any computation, I cannot find a way to write an external function that accept two arguments with different shapes. Any hint or exemple ?

Thanks,

Olivier

The python function :

Example Ferret external function written in Python
'''
import numpy
import pyferret

def ferret_init(id):
    '''Creates and returns the initialization dictionary for this PyEF'''
    initdict = { "numargs" : 2, "descript": "Test function",
                 "argnames": ("A", "Histogram boundaries"),
                     }
    return initdict

def ferret_compute(id, result, result_bad_flag, inputs, input_bad_flags):
    ''' Essai d'histogramme
    ARG1 is the array.
    ARG2 is the list of class boundaries
    '''

    badmask = ( numpy.fabs(inputs[pyferret.ARG1] - input_bad_flags[pyferret.ARG1]) < 1.0E-5 )
    goodmask = numpy.logical_not(badmask)

    result[badmask]  = input_bad_flags[pyferret.ARG1]
    result[goodmask] = inputs[pyferret.ARG1][goodmask]


Olivier Marti  - LSCE Bât 714 p. 1049
Tel : +33 1 69 08 77 27
mailto:olivier.marti@xxxxxxxxxxxx




--
Karl M. Smith, Ph.D.
JISAO Univ. Wash. and PMEL NOAA
"The contents of this message are mine personally and do
not necessarily reflect any position of the Government
or the National Oceanic and Atmospheric Administration."

[Thread Prev][Thread Next][Index]
Contact Us
Dept of Commerce / NOAA / OAR / PMEL / Ferret

Privacy Policy | Disclaimer | Accessibility Statement