Пример #1
0
int
m_Normals (Object *in, Object *out)
{
    char		*method;

    out[0] = NULL;

    if (in[0] == NULL)
    {
	DXSetError(ERROR_BAD_PARAMETER, "#10000", "input");
	goto error;
    }

    if (in[1])
    {
	if (! DXExtractString(in[1], &method))
	{
	    DXSetError(ERROR_BAD_PARAMETER, "#10200", "method");
	    goto error;
	}
    }
    else
	method = "positions";

    out[0] = _dxfNormals(in[0], method);

    if (out[0] == NULL || DXGetError() != ERROR_NONE)
	goto error;
    
    return OK;

error:
    DXDelete(out[0]);
    return ERROR;
}
Пример #2
0
static Error ExRunOnWorker (EXROJob job, int n)
{
    DXResetError ();
    (* job->func) (job->arg);
    job->code = DXGetError ();
    job->emsg = _dxf_ExCopyString (DXGetErrorMessage ());
    DXunlock(&job->done, exJID);
    return (OK);
}
Пример #3
0
/* 0 = input
 * 1 = string flags: "structure", "details", "render", "all"
 *     (default "all")
 *
 * which mean:    tell me about the input structure
 *                tell me about the geometry (positions, connections, bbox)
 *                tell me about the renderability
 */
int
m_Describe(Object *in, Object *out)
{
    char *opt = "all";


    if (!in[0]) {
	DescribeMsg("Object Description:");
	DescribeMsg("No input object was specified, or the input object is NULL.");
	return OK;
    }
    
    if (in[1] && !DXExtractString(in[1], &opt)) {
	DXErrorReturn(ERROR_BAD_PARAMETER, "Options string must be one of 'structure', `details', `render', or `all'");
    }
    
    /* ???  i should lcase opt, but have to make a copy first. */
    if (strcmp(opt, "all") && strcmp(opt, "structure") && 
	strcmp(opt, "details") && strcmp(opt, "render")) {
	
	DXErrorReturn(ERROR_BAD_PARAMETER, "Options string must be one of 'structure', `details', `render', or `all'");
    }
    
    DXBeginLongMessage();

    if (!strcmp(opt, "all"))
	DescribeMsg("Object Description:\n");

    if (!strcmp(opt, "all") || !strcmp(opt, "structure")) {
	if (!strcmp(opt, "structure"))
	    DescribeMsg("Object Structure:\n");
	if (!saytype(in[0], opt))
	    goto done;
    }

    if (!strcmp(opt, "all") || !strcmp(opt, "details")) {
	if (!strcmp(opt, "details"))
	    DescribeMsg("Object Details:\n");
	if (!saydata(in[0], opt))
	    goto done;
    }

    if (!strcmp(opt, "all") || !strcmp(opt, "render")) {
	if (!strcmp(opt, "render"))
	    DescribeMsg("Object Renderability:\n");
	if (!sayrender(in[0], opt))
	    goto done;
    }

    DescribeMsg("\n");
    DXEndLongMessage();

  done:
    return (DXGetError()==ERROR_NONE ? OK : ERROR);
}
Пример #4
0
int
m_FaceNormals (Object *in, Object *out)
{
    out[0] = NULL;

    if (in[0] == NULL)
    {
	DXSetError(ERROR_BAD_PARAMETER, "#10000", "input");
	goto error;
    }

    out[0] = _dxfNormals(in[0], "connections");

    if (out[0] == NULL || DXGetError() != ERROR_NONE)
	goto error;
    
    return OK;

error:
    DXDelete(out[0]);
    return ERROR;
}
Пример #5
0
static int
doLeaf(Object *in, Object *out)
{
  int result=0;
  Field field;
  Category category;
  Category lookup_category;
  int rank, shape[30];
  char *cat_comp;
  char *data_comp;
  char *lookup_comp;
  char name_str[256];
  char *opstr;
  int operation;
  int lookup_knt;
  int lookup_knt_provided = 0;
  Array cat_array = NULL;
  Array data_array = NULL;
  Array out_array = NULL;
  Array array = NULL;
  Array lookup_array = NULL;
  float *out_data;
  int data_knt, cat_knt;
  int out_knt=0;
  Type cat_type, data_type, lookup_type;
  float floatmax;
  ICH invalid;

  if (DXGetObjectClass(in[0]) == CLASS_FIELD)
  {
    field = (Field)in[0];

    if (DXEmptyField(field))
      return OK;
  }

  if (!DXExtractString((Object)in[1], &opstr))
	opstr = STR_COUNT;

  if (!strcmp(opstr, STR_COUNT))
    operation = STAT_COUNT;
  else if (!strcmp(opstr, STR_MEAN))
    operation = STAT_MEAN;
  else if (!strcmp(opstr, STR_SD))
    operation = STAT_SD;
  else if (!strcmp(opstr, STR_VAR))
    operation = STAT_VAR;
  else if (!strcmp(opstr, STR_MIN))
    operation = STAT_MIN;
  else if (!strcmp(opstr, STR_MAX))
    operation = STAT_MAX;
  else if (!strcmp(opstr, STR_ACCUM))
    operation = STAT_ACCUM;
  else
    operation = STAT_UNDEF;

  if (operation == STAT_UNDEF) {
    DXSetError(ERROR_BAD_PARAMETER, "statistics operation must be one of: count, mean, sd, var, min, max");
    goto error;
  }

  if (!DXExtractString((Object)in[2], &cat_comp))
	cat_comp = STR_DATA;
  if (!DXExtractString((Object)in[3], &data_comp))
	data_comp = STR_DATA;

  if (in[0])
  {
      if (DXGetObjectClass(in[0]) != CLASS_FIELD)
      {
        DXSetError(ERROR_BAD_CLASS, "\"input\" should be a field");
        goto error;
      }

      cat_array = (Array)DXGetComponentValue((Field)in[0], cat_comp);
      if (! cat_array)
      {
        DXSetError(ERROR_MISSING_DATA, "\"input\" has no \"%s\" categorical component", cat_comp);
        goto error;
      }

      if (DXGetObjectClass((Object)cat_array) != CLASS_ARRAY)
      {
        DXSetError(ERROR_BAD_CLASS, "categorical component \"%s\" of \"input\" should be an array", cat_comp);
        goto error;
      }

      if (!HasInvalid((Field)in[0], cat_comp, &invalid))
      {
        DXSetError(ERROR_INTERNAL, "Bad invalid component");
        goto error;
      }

      if (invalid)
      {
        DXSetError(ERROR_DATA_INVALID, "categorical component must not contain invalid data");
        goto error;
      }

      DXGetArrayInfo(cat_array, &cat_knt, &cat_type, &category, &rank, shape);
      if ( (cat_type != TYPE_BYTE && cat_type != TYPE_UBYTE && cat_type != TYPE_INT && cat_type != TYPE_UINT)
             || category != CATEGORY_REAL || !((rank == 0) || ((rank == 1)&&(shape[0] == 1))))
      {
        DXSetError(ERROR_DATA_INVALID, "categorical component %s must be scalar non-float", cat_comp);
        goto error;
      }

      if (operation != STAT_COUNT) {
        data_array = (Array)DXGetComponentValue((Field)in[0], data_comp);
        if (! data_array)
        {
          DXSetError(ERROR_MISSING_DATA, "\"input\" has no \"%s\" data component", data_comp);
          goto error;
        }

        if (DXGetObjectClass((Object)data_array) != CLASS_ARRAY)
        {
          DXSetError(ERROR_BAD_CLASS, "data component \"%s\" of \"input\" should be an array", data_comp);
          goto error;
        }

        DXGetArrayInfo(data_array, &data_knt, &data_type, &category, &rank, shape);
        if ( (data_type != TYPE_BYTE && data_type != TYPE_UBYTE && data_type != TYPE_INT && data_type != TYPE_UINT
             && data_type != TYPE_FLOAT && data_type != TYPE_DOUBLE)	
               || category != CATEGORY_REAL || !((rank == 0) || ((rank == 1)&&(shape[0] == 1))))
        {
          DXSetError(ERROR_DATA_INVALID, "data component \"%s\" must be scalar", data_comp);
          goto error;
        }

        if (data_knt != cat_knt)
        {
	  DXSetError(ERROR_DATA_INVALID, "category and data counts must be the same");
	  goto error;
        }
      }
  }

  if (in[4]) {
      if (DXExtractString((Object)in[4], &lookup_comp)) {
	    lookup_array = (Array)DXGetComponentValue((Field)in[0], lookup_comp);
	    if (!lookup_array)
	    {
	      DXSetError(ERROR_MISSING_DATA, "\"input\" has no \"%s\" lookup component", lookup_comp);
	      goto error;
	    }
      } else if (DXExtractInteger((Object)in[4], &lookup_knt)) {
	    lookup_knt_provided = 1;
	    out_knt = lookup_knt;
      } else if (DXGetObjectClass((Object)in[4]) == CLASS_ARRAY) {
	    lookup_array = (Array)in[4];
	    sprintf(name_str, "%s lookup", cat_comp);
	    lookup_comp = name_str;
      } else { 
            DXSetError(ERROR_DATA_INVALID, "lookup component must be string, integer, or array");
	    goto error;
      }
  } else {
      sprintf(name_str, "%s lookup", cat_comp);
      lookup_comp = name_str;
      lookup_array = (Array)DXGetComponentValue((Field)in[0], lookup_comp);
  } 

  if (lookup_array) {
    DXGetArrayInfo(lookup_array, &lookup_knt, &lookup_type, &lookup_category, &rank, shape);
    out_knt = lookup_knt;
  } else if (!lookup_knt_provided){
    if (!DXStatistics((Object)in[0], cat_comp, NULL, &floatmax, NULL, NULL)) {
      DXSetError(ERROR_INTERNAL, "Bad statistics on categorical component");
      goto error;
    }
    out_knt = (int)(floatmax+1.5);
  }

  out_array = DXNewArray(TYPE_FLOAT, CATEGORY_REAL, 0);
  if (! out_array)
    goto error;

  if (! DXSetAttribute((Object)out_array, "dep", (Object)DXNewString("positions")))
    goto error;

  if (! DXAddArrayData(out_array, 0, out_knt, NULL))
    goto error;

  if (out[0])
  {
    if (DXGetObjectClass(out[0]) != CLASS_FIELD)
    {
      DXSetError(ERROR_INTERNAL, "non-field object found in output");
      goto error;
    }

    if (DXGetComponentValue((Field)out[0], "data"))
      DXDeleteComponent((Field)out[0], "data");

    if (! DXSetComponentValue((Field)out[0], "data", (Object)out_array))
      goto error;

    if (lookup_array) {
      if (! DXSetComponentValue((Field)out[0], lookup_comp, (Object)lookup_array))
        goto error;
    }
  }
  else
  {
    out[0] = (Object)DXNewField();
    array = DXMakeGridPositions(1, out_knt, 0.0, 1.0);
    if (!array)
	goto error;
    DXSetComponentValue((Field)out[0], "positions", (Object)array);
    array = DXMakeGridConnections(1, out_knt);
    if (!array)
	goto error;
    DXSetComponentValue((Field)out[0], "connections", (Object)array);
    DXSetComponentValue((Field)out[0], "data", (Object)out_array);
    if (lookup_array) {
      if (! DXSetComponentValue((Field)out[0], lookup_comp, (Object)lookup_array))
        goto error;
    }
  }

  out_data = DXGetArrayData(out_array);
  if (! out_data)
    goto error;

  result = CategoryStatistics_worker(
  		out_data, cat_knt, out_knt, cat_array, data_array,
		cat_type, data_type, operation);

  if (! result) {
     if (DXGetError()==ERROR_NONE)
        DXSetError(ERROR_INTERNAL, "error return from user routine");
     goto error;
  }

  result = (DXEndField((Field)out[0]) != NULL);

error:
  return result;
}
Пример #6
0
Error m_SXRegrid( Object *in, Object *out ){
/*
*+
*  Name:
*     SXRegrid

*  Purpose:
*     samples a field at positions defined by a another field

*  Language:
*     ANSI C

*  Syntax:
*     output = SXRegrid( input, grid, nearest, radius, scale, exponent,
*                        coexp, type );

*  Classification:
*     Realisation

*  Description:
*     The SXRegrid module samples the "data" component of the "input"
*     field at the positions held in the "positions" component of the
*     "grid" field. It is similar to the standard "Regrid" module, but
*     provides more versatility in assigning weights to each input position,
*     the option of returning the sums of the weights or the weighted sum
*     instead of the weighted mean, and seems to be much faster. Both
*     supplied fields can hold scattered or regularly gridded points, and
*     need not contain "connections" components. The "data" component in the
*     "input" field must depend on "positions".
*
*     For each grid position, a set of near-by positions in the input
*     field are found (using "nearest" and "radius"). Each of these input
*     positions is given a weight dependant on its distance from the current
*     grid position. The output data value (defined at the grid position) can
*     be the weighted mean or weighted sum of these input data values, or
*     the sum of the weights (selected by "type").
*
*     The weight for each input position is of the form:
*
*        (d/d0)**exponent
*
*     where "d" is the distance from the current grid position to the
*     current input position. If a single value is given for "scale" then
*     that value is used for the d0 constant for all the near-by input
*     positions. If more than 1 value is given for "scale" then the first
*     value is used for the closest input position, the second value for the
*     next closest, etc. The last supplied value is used for any remaining
*     input positions. A value of zero for "scale" causes the
*     corresponding input position to be given zero weight.
*
*     If "coexp" is not zero, then the above weights are modified to
*     become:
*
*        exp( coexp*( (d/d0)**exponent ) )
*
*     If "nearest" is given an integer value, it specifies N, the maximum
*     number of near-by input positions to use for each output position.
*     The N input positions which are closest to the output position are
*     used. If the string "infinity" is given, then all input positions
*     closer than the distance given by "radius" are used. Using "radius",
*     you may specify a maximum radius (from the output position) within
*     which to find the near-by input positions. If the string "infinity"
*     is given for "radius" then no limit is placed on the radius.

*  Parameters:
*     input = field (Given)
*        field or group with positions to regrid [none]
*     grid = field (Given)
*        grid to use as template [none]
*     nearest = integer or string (Given)
*        number of nearest neighbours to use, or "infinity" [1]
*     radius = scalar or string (Given)
*        radius from grid point to consider, or "infinity" ["infinity"]
*     scale = scalar or vector or scalar list (Given)
*        scale lengths for weights [1.0]
*     exponent = scalar (Given)
*        weighting exponent [1.0]
*     coexp = scalar (Given)
*        exponential co-efficient for weights [0.0]
*     type = integer (Given)
*        type of output values required: 0 - weighted mean, 1 - weighted sum,
*                                        2 - sum of weights [0]
*     output = field (Returned)
*        regridded field

*  Components:
*     All components except the "data" component are copied from the "grid"
*     field. The output "data" component added by this module depends on
*     "positions". An "invalid positions" component is added if any output
*     data values could not be calculated (e.g. if there are no near-by input
*     data values to define the weighted mean, or if the weights are too
*     large to be represented, or if the input grid position was invalid).

*  Examples:
*     This example maps the scattered data described in "CO2.general" onto a
*     regular grid, and displays it. SXRegrid is used to find the data value
*     at the nearest input position to each grid position.
*
*        input = Import("/usr/lpp/dx/samples/data/CO2.general")$
*        frame17 = Select(input,17);
*        camera = AutoCamera(frame17);
*        grid = Construct([-100,-170],deltas=[10,10],counts=[19,34]);
*        regrid = SXRegrid(frame17,grid);
*        coloured = AutoColor(regrid);
*        Display(coloured,camera);
*
*     The next example produces a grid containing an estimate of the density
*     of the scattered points (i.e. the number of points per unit area). The
*     positions of the original scattered points are shown as dim grey
*     circles. SXRegrid finds the 5 closest input positions at each grid
*     position. Zero weight is given to the closest 3 positions. The fourth
*     position has a weight which is half the density of the points within the
*     circle passing through the fourth point (i.e. if the fourth point
*     is at a distance D from the current grid position, there are 3 points
*     within a circle of radius D, so the density within that circle is
*     3/(PI*(D**2)) ). The fifth position has a weight which is half the
*     density of the points within the circle passing through the fifth
*     point. The output data value is the sum of the weights (because
*     "type" is set to 2), which is the mean of the densities within the
*     circles touching the fourth and fifth points.
*
*        input = Import("/usr/lpp/dx/samples/data/CO2.general")$
*        frame17 = Select(input,17);
*        camera = AutoCamera(frame17);
*        glyphs=AutoGlyph(frame17,scale=0.1,ratio=1);
*        glyphs=Color(glyphs,"dim grey");
*        grid = Construct([-100,-170],deltas=[10,10],counts=[19,34]);
*        density=SXRegrid(frame17,grid,nearest=5,scale=[0,0,0,0.691,0.798],
*                         exponent=-2,type=2);
*        coloured = AutoColor(density);
*        collected=Collect(coloured,glyphs);
*        Display(collected,camera);

*  See Also:
*     SXBin, ReGrid, Map, Construct

*  Returned Value:
*     OK, unless an error occurs in which case ERROR is returned and the
*     DX error code is set.

*  Copyright:
*     Copyright (C) 1995 Central Laboratory of the Research Councils.
*     All Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful,but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 51 Franklin Street,Fifth Floor, Boston, MA
*     02110-1301, USA

*  Authors:
*     DSB: David Berry (STARLINK)
*     {enter_new_authors_here}

*  History:
*     3-OCT-1995 (DSB):
*        Original version
*     {enter_further_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*-
*/


/*  Local Variables: */

      Category cat;          /* Array category type */
      float    coexp;        /* Exponential co-efficient for weights */
      Type     dtype;        /* Type of current input data array */
      float    ext;          /* Amount by which to extend grid bounds */
      int      fld;          /* Field counter */
      Object   grid;         /* The grid object */
      float   *gridpos;      /* Pointer to grid positions array */
      int      i;            /* Loop count */
      void    *indata[MAXFLD];/* Pointer to input data array */
      float   *inpos;        /* Pointer to input positions array */
      Array    inpos_array;  /* Input positions array */
      Object   input;        /* A copy of the input object */
      int      iopt;         /* Index of selected option */
      int      j;            /* Loop count */
      float    lbnd[3];      /* Lower bounds of grid */
      char    *opt;          /* Textual option for a parameter value */
      float    radius;       /* Max. radius for contributing input positions */
      char     more;         /* Are there more input fields to do? */
      int      nearest;       /* Max. no. of input positions which can contribute to an output position */
      Fpair   *next;         /* The next Fpair structure in the linked list */
      int      ndim;         /* No. of dimensions in grid positions array */
      int      nfld;         /* No. of fields sharing current positions array */
      int      npos;         /* No. of input positions */
      int      npindim;      /* No. of dimensions in input positions array */
      int      nsamp;        /* No. of grid positions */
      int      nscale;       /* No. of scale distances supplied */
      int      outbad[MAXFLD];/* No. of invalid output positions in each field*/
      void    *outdata[MAXFLD];/* Pointers to output data arrays */
      Array    outdata_array;/* Output data array */
      Object   output;       /* The output object */
      int      outtype;      /* Type of output values required */
      float    exponent;     /* Power for weights */
      int      rank;         /* Array rank */
      float    rsc;          /* Reciprocal squared scale distance*/
      float   *rscale;       /* Scale distances for weights */
      int      tag;          /* The tag for the current input positions array */
      Type     type;         /* Array numeric type */
      float    ubnd[3];      /* Upper bounds of grid */
      int      veclen[MAXFLD];/* Dimensionality of each input data array */


/*  Initialise all created objects so that they can safely be deleted if
 *  an error occurs. */

      input = NULL;
      output = NULL;
      grid = NULL;
      outdata_array = NULL;


/*  Check that the "input" object has been supplied. */

      if( !in[0] ) {
         DXSetError( ERROR_BAD_PARAMETER, "missing parameter \"input\"." );
         goto error;
      }


/*  Remove (cull) all invalid positions and connections from the input. It is
 *  necessary to take a copy of the input first, because the input object
 *  itself cannot be modified. */

      input = DXCopy( in[0], COPY_STRUCTURE );
      if( !DXCull( input ) ) goto error;


/*  Check that the "grid" object has been supplied. */

      if( !in[1] ) {
         DXSetError( ERROR_BAD_PARAMETER, "missing parameter \"grid\"." );
         goto error;
      }


/*  Get a pointer to an array holding the grid positions, and get the
 *  size and shape of the grid. Any invalid positions are flagged with the
 *  value FLT_MAX (defined in float.h). */

      gridpos = SXGetGrid( in[1], &nsamp, &ndim, lbnd, ubnd, &grid );
      if( !gridpos ) goto error;


/*  Get the number of input positions allowed to contribute to each
 *  output position. */

      if( !in[2] ){
         nearest = 1;

      } else {

         opt = "infinity";
         if( !SXGet0is( "nearest", in[2], INT_MAX, 1, 1, &opt, &nearest, &iopt ) ) goto error;
         if( iopt == 0 ) nearest = INT_MAX;

      }


/*  Get the maximum radius for input positions which contribute to each
 *  output position. */

      if( !in[3] ){
         radius = FLT_MAX;

      } else {

         opt = "infinity";
         if( !SXGet0rs( "radius", in[3], FLT_MAX, 0.0, 1, &opt, &radius, &iopt ) ) goto error;
         if( iopt == 0 ) radius = FLT_MAX;

      }


/*  If a maximum radius has been given, extend the bounds by one radius
 *  at each end to catch some extra input positions. Otherwise, extend
 *  the bounds by 10%. */

      if( radius < FLT_MAX ){
         for( j=0; j<ndim; j++ ){
            lbnd[j] -= radius;
            ubnd[j] += radius;
         }

      } else {
         for( j=0; j<ndim; j++ ){
            ext = 0.1*( ubnd[j] - lbnd[j] );
            lbnd[j] -= ext;
            ubnd[j] += ext;
         }

      }


/*  Get the scale distances used to create weights for each input
 *  position. Convert them to squared reciprocal scale distances. If
 *  no value is supplied for the "scale" parameter, use a single scale
 *  length of 1.0 */

      if( !in[4] ){
         rsc = 1.0;
         rscale = &rsc;
         nscale = 1;

      } else {
         rscale = SXGet1r( "scale", in[4], &nscale );
         if( !rscale ) goto error;

         for( i=0; i<nscale; i++ ) {
            rsc = rscale[i];
            if( rsc != 0.0 ){
               rscale[i] = 1.0/(rsc*rsc);
            } else {
               rscale[i] = 0.0;
            }
         }

      }


/*  Get the exponent used to create weights for each input position. */

      if( !in[5] ){
         exponent = 1.0;
      } else {
         if( !SXGet0rs( "exponent", in[5], FLT_MAX, -FLT_MAX, 0, &opt, &exponent, &iopt ) ) goto error;
      }


/*  Get the co-efficient to used in the exponential when creating weights for
 *  each input position. */

      if( !in[6] ){
         coexp = 0.0;
      } else {
         if( !SXGet0rs( "coexp", in[6], FLT_MAX, -FLT_MAX, 0, &opt, &coexp, &iopt ) ) goto error;
      }


/*  Get the type of output value required. */

      if( !in[7] ){
         outtype = 0;
      } else {
         if( !SXGet0is( "type", in[7], 2, 0, 0, &opt, &outtype, &iopt ) ) goto error;
      }


/*  Produce a copy of the "input" object to use as the output, replacing all
 *  fields within it with the grid field. Also form a linked list of Fpair
 *  structures describing the fields. */

      output = SXMakeOut( input, (Field) grid, 1, 1, 3, "positions" );
      if( !output ) goto error;


/*  Abort if no fields were found. */

      if( !head ) {
         DXSetError( ERROR_DATA_INVALID, "no fields found in \"input\"." );
         goto error;
      }


/*  Go through the list of fields looking for fields which share the same
 *  positions component. */

      more = 1;
      while( more ){


/*  Find the first field with a non-zero positions tag. */

         next = head;
         while( next && !next->postag ) next = next->next;


/*  If no non-zero positions tags were found, we've finished. */

         if( !next ){
            more = 0;
            break;
         }


/*  Find the input positions array. Get its shape, size and type. Check it is
 *  usable. */

         inpos_array = (Array) next->pos;
         if( !DXGetArrayInfo( inpos_array, &npos, &type, &cat, &rank, &npindim ) ) goto error;

         if( type != TYPE_FLOAT ){
            DXSetError( ERROR_DATA_INVALID, "positions component in \"input\" is not of type FLOAT." );
            goto error;
         }

         if( cat != CATEGORY_REAL ){
            DXSetError( ERROR_DATA_INVALID, "positions component in \"input\" is not of category REAL." );
            goto error;
         }

         if( rank > 1 ){
            DXSetError( ERROR_DATA_INVALID, "rank %d positions component found in \"input\".", rank );
            goto error;
         }

         if( rank == 0 ){   /* Scalar data is equivalent to 1-d vector data */
            rank = 1;
            npindim = 1;
         }

         if( npindim != ndim ){
            DXSetError( ERROR_DATA_INVALID, "dimensionality of \"input\" (%d) does not match \"grid\" (%d).", npindim, ndim );
            goto error;
         }


/*  Get a pointer to the positions values. */

         inpos = (float *) DXGetArrayData( inpos_array );


/*  Find all fields which have the same positions tag and the same data
 *  type. */

         tag = next->postag;
         dtype = next->datatype;

         nfld = 0;
         while( next ){

            if( next->postag == tag && next->datatype == dtype ){


/*  Increment the number of fields found so far which share this
 *  positions component. */

               nfld++;

               if( nfld > MAXFLD ){
                  DXSetError( ERROR_MAX, "\"input\" has too many fields.", MAXFLD );
                  goto error;
               }


/*  Store a pointer to the input data array, and its dimensionality. */

              indata[nfld-1] = (void *) DXGetArrayData( (Array) next->data );
              veclen[nfld-1] = next->datalen;


/*  Make a new array to hold the output data values. The output data will
 *  have the same dimensionality as the input data unless the required output
 *  data is "sum of weights" (i.e. if parameter "type" is 2), in which case the
 *  output data will be scalar. */

              if( outtype == 2 ) veclen[nfld-1] = 1;

              outdata_array = DXNewArrayV( dtype, CATEGORY_REAL, 1, &veclen[nfld-1] );
              if( !outdata_array ) goto error;

              if( !DXAddArrayData( outdata_array, 0, nsamp, NULL ) ) goto error;


/*  Get a pointer to the output data array. */

              outdata[nfld-1] = (void *) DXGetArrayData( outdata_array );
              if( !outdata[nfld-1] ) goto error;


/*  Place the new data component in the output field, and indicate that
 *  it now does not need to be deleted explicitly in the event of an error. */

              if( !DXSetComponentValue( next->outfld, "data", (Object) outdata_array ) ) goto error;
              outdata_array = NULL;


/*  Indicate that the data component of the output field has been
 *  changed. */

              DXChangedComponentValues( next->outfld, "data" );


/*  Indicate that the data values are dependant on positions. */

              if( !DXSetComponentAttribute( next->outfld, "data", "dep",
                                        (Object) DXNewString("positions")) ) goto error;

            }

            next = next->next;

         }


/*  Now sample the input data arrays at the output positions, storing the
 *  resulting sample values in the output data arrays. */

         if( dtype == TYPE_FLOAT ){
            if( ! SXSampleF( nfld, ndim, veclen, npos, inpos, (float **)indata,
                             nsamp, gridpos, (float **) outdata, lbnd, ubnd,
                             nearest, radius, rscale, nscale, exponent, coexp,
                             outtype, outbad ) ) goto error;
         } else {
            if( ! SXSampleD( nfld, ndim, veclen, npos, inpos, (double **)indata,
                             nsamp, gridpos, (double **) outdata, lbnd, ubnd,
                             nearest, radius, rscale, nscale, exponent, coexp,
                             outtype, outbad ) ) goto error;
         }


/*  Loop round all the fields that have just been created. */

         next = head;
         fld = 0;
         while( next ){
            if( next->postag == tag ){


/*  Create invalid positions components in each output field which have any
 *  undefined data values */

               if( outbad[fld] ){
                  if( dtype == TYPE_FLOAT ){
                     if( !SXSetInvPosF( (Object) next->outfld, nsamp, veclen[fld],
                                        (float *) outdata[fld], "positions" ) ) goto error;
                  } else {
                     if( !SXSetInvPosD( (Object) next->outfld, nsamp, veclen[fld],
                                        (double *) outdata[fld], "positions" ) ) goto error;
                  }
               }



/*  Complete the construction of this output field. */

               DXEndField( next->outfld );


/*  Increment the field index, and indicate that this input field has
 *  been done. */

               fld++;
               next->postag = 0;

            }

            next = next->next;

         }


      }

error:

/*  Free the storage used to hold the link list of Fpair structures
 *  describing the fields in the "input" object. */

      while( head ){
         next = head->next;
         DXFree( (Pointer) head );
         head = next;
      }


/*  Delete the copy of the input objects. Return the "output" object with a good status. */

      DXDelete( grid );
      DXDelete( input );


/*  If all is OK, return the "output" object with a good status. */

      if( DXGetError() == ERROR_NONE ){
         out[0] = output;
         return( OK );


/*  If an error has occurred, ensure temporary objects are deleted and return
 *  with a bad status. */

      } else {
         DXDelete( (Object) outdata_array );
         DXDelete( output );
         return( ERROR );
      }

}
Пример #7
0
static Error ExProcessTaskGroup (int sync)
{
    Error               ret	= ERROR;
    EXTaskGroup		tg;
    EXTask		task;
    int			i, j;
    int			todo;
#if 0
    volatile int	*count;		/* task group counter		*/
#endif
    int			totalTodo;
#define NUM_TASKS_ALLOCED 256
    Pointer		_args[NUM_TASKS_ALLOCED];
    PFI			_funcs[NUM_TASKS_ALLOCED];
    int			_repeats[NUM_TASKS_ALLOCED];
    Pointer		*args	= _args;
    PFI			*funcs	= _funcs;
    int			*repeats = _repeats;
    int			status;
    WorkIndex 		_ilist[NUM_TASKS_ALLOCED];
    WorkIndex 		*ilist	= _ilist;
    ErrorCode		ecode;
    char		*emsg;
    EXTask		myTask	= NULL;
    int			myIter	= 0;
    
    if (EMPTY)
	return (OK);
    
    POP (tg);
    if (tg->nused == 0)
    {
	ExDestroyTaskGroup (tg);
	return (OK);
    }

    DXMarkTime ("start parallel");
    /*
     * Remember whether or not this is a syncronous task group.
     */

    ecode = DXGetError ();
    emsg  = DXGetErrorMessage ();

    if (ecode != ERROR_NONE || *emsg != '\0')
    {
	if (ecode != ERROR_NONE)
	    DXWarning ("#4840");
	else
	    DXWarning ("#4850");
	
	tg->error = ecode;
	tg->emsg  = _dxf_ExCopyString (emsg);
    }

    tg->sync  = sync;
    todo = tg->nused;

    status = get_status ();

    /*
     * Only bother to sort if the tasks actually have different cost
     * estimates associated with them.
     */
    if (todo > NUM_TASKS_ALLOCED)
    {
	ilist = (WorkIndex *) DXAllocateLocal (todo * sizeof (WorkIndex));
	if (ilist == NULL)
	    goto error;
    }
    task = tg->tasks;
    for (i = 0; i < todo; ++i)
    {
	ilist[i].task = task + i;
	ilist[i].work = task[i].work;
        _dxfCopyContext(&(task[i].taskContext), _dxd_exContext);
    }

    if (tg->minwork != tg->maxwork)
	QUICKSORT (ilist, todo);
#ifdef TASK_TIME
    DXMarkTimeLocal ("finish sort");
#endif

    /*
     * Schedule/Execute the tasks appropriately.
     */
    if (todo > NUM_TASKS_ALLOCED) 
    {
	funcs   = (PFI     *) DXAllocateLocal (todo * sizeof (PFI    ));
	args    = (Pointer *) DXAllocateLocal (todo * sizeof (Pointer));
	repeats = (int     *) DXAllocateLocal (todo * sizeof (int    ));
	if (funcs == NULL || args == NULL || repeats == NULL)
	    goto error;
    }

    /* Save a task for the executer to execute */
    i = 0;
    if (sync)
    {
	myTask = ilist[i].task;
	myIter = ilist[i].task->repeat - 1;
	ilist[i].task->repeat--;
	if (ilist[i].task->repeat == 0) 
	{
	    i = 1;
	}
    }
	
    totalTodo = 1;
    for (j = 0; i < todo; j++, i++)
    {
	funcs[j] = ExProcessTask;
	args[j] = (Pointer) ilist[i].task;
	totalTodo += (repeats[j] = ilist[i].task->repeat);
    }
    tg->ntodo = totalTodo;
    if (ilist[0].task->repeat == 0)
    {
	--todo;
    }


#ifdef TASK_TIME
    DXMarkTimeLocal ("queue all tasks");
#endif
    _dxf_ExRQEnqueueMany (todo, funcs, args, repeats, (long) tg, 0, FALSE);
#ifdef TASK_TIME
    DXMarkTimeLocal ("queued all tasks");
#endif

    if (funcs != _funcs)
	DXFree ((Pointer)funcs);
    if (args != _args)
	DXFree ((Pointer)args);
    if (repeats != _repeats)
	DXFree ((Pointer)repeats);
    if (ilist != _ilist)
	DXFree ((Pointer)ilist);

    if (! sync)
    {
	ret = OK;
    }
    else 
    {
        int knt;

	/*
	 * This processor is now restricted to processing tasks in this
	 * task group.  Once it can no longer get a job in this task group
	 * from the run queue then just spin and wait for all of the outstanding
	 * tasks in the group to complete.
	 */

#ifdef TASK_TIME
	DXMarkTimeLocal ("tasks enqueued");
#endif
	/* Do the task that I saved above as myTask */
	if (myTask != NULL)
	    ExProcessTask (myTask, myIter);

#if 0
before the changes made to fix bugs found when debugging
SMP linux -- gda

	count = &tg->ntodo;
	while (*count > 0)
	{
	    if (! _dxf_ExRQDequeue ((long) tg))
		break;
	}

	DXMarkTimeLocal ("waiting");

	set_status (PS_JOINWAIT);

	/* Every 100 times of checking count, try to see if anyone added
	 * on to the queue.
	 */
	while (*count > 0)
	{
	    _dxf_ExRQDequeue ((long)tg);
	    for (i = 0; *count && i < 100; ++i)
		;
	}

#else

        do
        {
            DXlock(&tg->lock, 0);
            knt = tg->ntodo;
            DXunlock(&tg->lock, 0);

            _dxf_ExRQDequeue ((long) tg);
        } while(knt);

#endif

	DXMarkTimeLocal ("joining");

	set_status (status);

	ret = (tg->error == ERROR_NONE) ? OK : ERROR;
	if (ret != OK)
	    DXSetError (tg->error, tg->emsg? tg->emsg: "#8360");

	ExDestroyTaskGroup (tg);
    }

    DXMarkTime ("end parallel");
    return (ret);

error:
    if (funcs != _funcs)
	DXFree ((Pointer) funcs);
    if (args != _args)
	DXFree ((Pointer) args);
    if (repeats != _repeats)
	DXFree ((Pointer) repeats);
    if (ilist != _ilist)
	DXFree ((Pointer) ilist);
    return (ret);
}
Пример #8
0
static Error ExProcessTask (EXTask t, int iteration)
{
    EXTaskGroup		tg;
    Pointer		arg;		/* task argument pointer	*/
    ErrorCode		ecode;		/* error code			*/
#if 0
    int			ntodo;		/* number left in group		*/
#endif
    char		*emsg;
    Error		returnVal;
    int			status;
    EXTaskGroup		oldTG;
    Context             savedContext;
    int		  	lastTask;

    oldTG = runningTG;
    ecode = ERROR_NONE;
    emsg  = NULL;

    runningTG = tg    = t->tg;

    arg = (t->nocopy || t->arg) ? t->arg : (Pointer) t->data;

    DXResetError ();
#if 0
    savedContext = _dxd_exContext; /* save current context */
    _dxd_exContext = t->taskContext;  /* move task context to global context */
#endif
    _dxfCopyContext(&savedContext, _dxd_exContext);
    _dxfCopyContext(_dxd_exContext, &(t->taskContext));
    status = get_status ();
    set_status (PS_RUN);
    DXMarkTimeLocal ("start task");

    returnVal = (*t->func) (arg, iteration);
#if 0
    _dxd_exContext = savedContext; /* restore original context */
#endif
    _dxfCopyContext(_dxd_exContext, &savedContext);

    DXMarkTimeLocal ("end task");
    set_status (status);

    /*
     * Check for errors, if we are running without waiting, skip
     * error checking.  If the user didn't DXSetError and he didn't return
     * ERROR, no error checking.  If we have had an error in the past, 
     * don't bother getting the error stuff.
     */
    if (! tg->sync)
	goto countdown;

    ecode = DXGetError ();
    if (ecode == ERROR_NONE && returnVal == OK)
	goto countdown;

    if (ecode != ERROR_NONE && returnVal == OK)
    {
	returnVal = ERROR;
	DXWarning ("#4720",t->taskContext.graphId,
		_dxf_ExGFuncPathToString(_dxd_exCurrentFunc));
    }
    if (ecode == ERROR_NONE && returnVal == ERROR)
    {
	ecode = ERROR_INTERNAL;
	emsg = "#8350";
	goto copymessage;
    }

    if (tg->error != ERROR_NONE)
	goto countdown;

    emsg = DXGetErrorMessage ();

#define	L_ERROR		2048
copymessage:
    if (emsg)
    {
	char	lbuf[L_ERROR];
	int	len;

	len = strlen (emsg);
	len = len >= L_ERROR ? L_ERROR - 1 : len;
	strncpy (lbuf, emsg, len);
	lbuf[len] = 0;
	emsg = _dxf_ExCopyString (lbuf);
    }

countdown:


#if 0
before the changes made to fix bugs found when debugging
SMP linux -- gda


    DXlock (&tg->lock, exJID);
    ntodo = --(tg->ntodo);
    if (ecode != ERROR_NONE && tg->error == ERROR_NONE)
    {
	tg->error = ecode;
	tg->emsg  = emsg;
	emsg      = NULL;
    }
    DXunlock (&tg->lock, exJID);

    DXFree ((Pointer) emsg);

    /* If this tg was run asyncronously and needs to be destroyed, schedule
     * the destruction on the creating processor.
     */
    if ((ntodo == 0) && (! tg->sync))
	_dxf_ExRQEnqueue (ExDestroyTaskGroup, (Pointer) tg, 1, 0, tg->procId, FALSE);

#else

    /*
     * Decrement the task group task counter.  Was this the last task?
     */
    DXlock (&tg->lock, exJID);
    tg->ntodo --;
    lastTask = (tg->ntodo == 0);
    DXunlock (&tg->lock, exJID);

    if (tg->sync == 0)
    {
        /*
         * Its an asynchronous task group.
         * Forget about errors... no-one is waiting for them.
         */
        DXFree ((Pointer) emsg);

        /*
         * If this was the last task in the task group then arrange for the
         * task group to be deleted.
         */
        if (lastTask)
            _dxf_ExRQEnqueue (ExDestroyTaskGroup, (Pointer)tg, 1, 0, tg->procId, FALSE);
    }
    else
    {
        /*
         * A synchronous task group... the creator is waiting for
         * ntodo to go to zero (and the lock to be available).
         * If there's an error conditition with the current task and
         * there wasn't one stashed in the task group, then stash
         * this one.
         */
        if (ecode != ERROR_NONE && tg->error == ERROR_NONE)
        {
            tg->error = ecode;
            tg->emsg  = emsg;
            emsg      = NULL;
        }
    }


#endif
    
    if (t->exdelete)
	DXFree ((Pointer) t);
    runningTG = oldTG;
    return (ecode == ERROR_NONE ? OK : ERROR);
}
Пример #9
0
Error m_SXBin( Object *in, Object *out ){
/*
*+
*  Name:
*     SXBin

*  Purpose:
*     bins a field into a grid defined by a another field

*  Language:
*     ANSI C

*  Syntax:
*     output = SXBin( input, grid, type );

*  Classification:
*     Realization

*  Description:
*     The SXBin module bins the "data" component of the "input" field into
*     the bins defined by the "connections" component of the "grid" field.
*     The input field can hold scattered or regularly gridded points, but
*     the "data" component must depend on "positions". The "grid" field must
*     contain "connections" and "positions" components but need not contain
*     a "data" component. The input"data" component must be either TYPE_FLOAT
*     or TYPE_DOUBLE.
*
*     The "data" component in the "output" field contains either the mean
*     or sum of the "input" data values falling within each connection, or
*     the number of data values falling within each connection, as specified
*     by "type".
*
*     When binning a regular grid into another regular grid, beware of the
*     tendancy to produce artificial large scale structure representing the
*     "beat frequency" of the two grids.

*  Parameters:
*     input = field (Given)
*        field or group with positions to bin [none]
*     grid = field (Given)
*        grid to define the bins [none]
*     type = integer (Given)
*        type of output values required: 0 - mean, 1 - sum,
*                                        2 - count [0]
*     output = field (Returned)
*        bined field

*  Components:
*     All components except the "data" component are copied from the "grid"
*     field. The output "data" component added by this module depends on
*     "connections". An "invalid connections" component is added if any output
*     data values could not be calculated (e.g. if the mean is required of an
*     empty bin).

*  Examples:
*     This example bins the scattered data described in "CO2.general" onto a
*     regular grid, and displays it. SXBin is used to find the mean data
*     value in each grid connection.
*
*        input = Import("/usr/lpp/dx/samples/data/CO2.general")$
*        frame17 = Select(input,17);
*        camera = AutoCamera(frame17);
*        grid = Construct([-100,-170],deltas=[10,10],counts=[19,34]);
*        bin = SXBin(frame17,grid);
*        coloured = AutoColor(bin);
*        Display(coloured,camera);
*
*     This example produces a grid containing an estimate of the density of
*     the scattered points (i.e. the number of points per unit area). The
*     positions of the original scattered points are shown as dim grey
*     circles. SXBin finds the number of input positions in each bin,
*     Measure finds the area of each bin, and Compute divides the counts
*     by the areas to get the densities:
*
*        input = Import("/usr/lpp/dx/samples/data/CO2.general")$
*        frame17 = Select(input,17);
*        camera = AutoCamera(frame17);
*        glyphs = AutoGlyph(frame17,scale=0.1,ratio=1);
*        glyphs = Color(glyphs,"dim grey");
*        grid = Construct([-100,-170],deltas=[40,40],counts=[6,10]);
*        counts = SXBin(frame17,grid,type=2);
*        areas = Measure(counts,"element");
*        density = Compute("$0/$1",counts,areas);
*        coloured = AutoColor(density);
*        collected=Collect(coloured,glyphs);
*        Display(collected,camera);

*  See Also:
*     SXRegrid, Map, Construct, Measure

*  Returned Value:
*     OK, unless an error occurs in which case ERROR is returned and the
*     DX error code is set.

*  Copyright:
*     Copyright (C) 1995 Central Laboratory of the Research Councils.
*     All Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful,but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 51 Franklin Street,Fifth Floor, Boston, MA
*     02110-1301, USA

*  Authors:
*     DSB: David Berry (STARLINK)
*     {enter_new_authors_here}

*  History:
*     9-OCT-1995 (DSB):
*        Original version
*     {enter_further_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*-
*/


/*  Local Variables: */

      Array    a;            /* Array to hold reduced dimension positions */
      float   *a_ptr;        /* Pointer to reduced dimension positions */
      Category cat;          /* Array category type */
      Type     dtype;        /* Type of current input data array */
      int      fld;          /* Field counter */
      Object   grid;         /* The grid object */
      int      i;            /* Loop count */
      void    *indata[MAXFLD];/* Pointer to input data array */
      float   *inpos;        /* Pointer to input positions array */
      Array    inpos_array;  /* Input positions array */
      Object   input;        /* A copy of the input object */
      Interpolator interp;   /* Interpolator for grid */
      int      j;            /* Loop count */
      Array    map;          /* Map from input position to output bin number */
      int     *map_ptr;      /* Pointer to map */
      char     more;         /* Are there more input fields to do? */
      Fpair   *next;         /* The next Fpair structure in the linked list */
      int      ndim;         /* No. of dimensions in grid positions array */
      int      nfld;         /* No. of fields sharing current positions array */
      int      npos;         /* No. of input positions */
      int      npindim;      /* No. of dimensions in input positions array */
      int      nbin;         /* No. of grid positions */
      int      outbad[MAXFLD];/* No. of invalid output positions in each field*/
      void    *outdata[MAXFLD];/* Pointers to output data arrays */
      Array    outdata_array;/* Output data array */
      Object   output;       /* The output object */
      int      outtype;      /* Type of output values required */
      float   *pa;           /* Pointer to next reduced dimension position */
      float   *pin;          /* Pointer to next full dimension position */
      int      rank;         /* Array rank */
      int      tag;          /* The tag for the current input positions array */
      Type     type;         /* Array numeric type */
      int      veclen[MAXFLD];/* Dimensionality of each input data array */
      int     *work;         /* Pointer to work array */


/*  Initialise all created objects so that they can safely be deleted if
 *  an error occurs. */

      input = NULL;
      output = NULL;
      grid = NULL;
      outdata_array = NULL;
      work = NULL;
      a = NULL;


/*  Check that the "input" object has been supplied. */

      if( !in[0] ) {
         DXSetError( ERROR_BAD_PARAMETER, "missing parameter \"input\"." );
         goto error;
      }


/*  Remove (cull) all invalid positions and connections from the input. It is
 *  necessary to take a copy of the input first, because the input object
 *  itself cannot be modified. */

      input = DXCopy( in[0], COPY_STRUCTURE );
      if( !DXCull( input ) ) goto error;


/*  Check that the "grid" object has been supplied. */

      if( !in[1] ) {
         DXSetError( ERROR_BAD_PARAMETER, "missing parameter \"grid\"." );
         goto error;
      }


/*  Create an interpolator which identifies the grid connection containing any
 *  given position. */

      interp = SXGetIntp( in[1], &nbin, &ndim, &grid );
      if( !interp ) goto error;


/*  Allocate a work array for use by SXBinD or SXBinF. */

      work = (int *) DXAllocate( sizeof( int )*nbin );
      if( !work ) goto error;


/*  Get the type of output value required. */

      if( !in[2] ){
         outtype = 0;
      } else {
         if( !SXGet0is( "type", in[2], 2, 0, 0, NULL, &outtype, NULL ) ) goto error;
      }


/*  Produce a copy of the "input" object to use as the output, replacing all
 *  fields within it with the grid field. Also form a linked list of Fpair
 *  structures describing the fields. */

      output = SXMakeOut( input, (Field) grid, 1, 1, 3, "positions" );
      if( !output ) goto error;


/*  Abort if no fields were found. */

      if( !head ) {
         DXSetError( ERROR_DATA_INVALID, "no fields found in \"input\"." );
         goto error;
      }


/*  Go through the list of fields looking for fields which share the same
 *  positions component. */

      more = 1;
      while( more ){


/*  Find the first field with a non-zero positions tag. */

         next = head;
         while( next && !next->postag ) next = next->next;


/*  If no non-zero positions tags were found, we've finished. */

         if( !next ){
            more = 0;
            break;
         }


/*  Find the input positions array. Get its shape, size and type. Check it is
 *  usable. */

         inpos_array = (Array) next->pos;
         if( !DXGetArrayInfo( inpos_array, &npos, &type, &cat, &rank, &npindim ) ) goto error;

         if( type != TYPE_FLOAT ){
            DXSetError( ERROR_DATA_INVALID, "positions component in \"input\" is not of type FLOAT." );
            goto error;
         }

         if( cat != CATEGORY_REAL ){
            DXSetError( ERROR_DATA_INVALID, "positions component in \"input\" is not of category REAL." );
            goto error;
         }

         if( rank > 1 ){
            DXSetError( ERROR_DATA_INVALID, "rank %d positions component found in \"input\".", rank );
            goto error;
         }

         if( rank == 0 ){   /* Scalar data is equivalent to 1-d vector data */
            rank = 1;
            npindim = 1;
         }

         if( npindim < ndim ){
            DXSetError( ERROR_DATA_INVALID, "dimensionality of \"input\" (%d) is less than \"grid\" (%d).", npindim, ndim );
            goto error;
         }


/*  Get a pointer to the positions values. */

         inpos = (float *) DXGetArrayData( inpos_array );


/*  If the number of dimensions in the input positions is greater than the
 *  number of dimensions in the grid, remove trailing dimensions from the
 *  input positions so that they match the dimensionality of the grid. */

         if( npindim > ndim ){
            a = DXNewArrayV( TYPE_FLOAT, CATEGORY_REAL, 1, &ndim );
            if( !DXAddArrayData( a, 0, npos, NULL ) ) goto error;
            a_ptr = (float *) DXGetArrayData( a );

            for( i=0; i<npos; i++ ){
               pin = inpos + i*npindim;
               pa = a_ptr + i*ndim;
               for(j=0;j<ndim;j++) pa[j] = pin[j];
            }

            inpos_array = a;

         } else {
            a = NULL;
         }

/*  Create an array of the same shape and size as the input positions
 *  array, which holds integer identifiers for the grid connections
 *  containing each input position. These identifiers start at 1 and
 *  go upto nbin. Positions returned holding an identifier of zero do
 *  not fall within the supplied grid. */

         map = (Array) DXMap( (Object) inpos_array, (Object) interp,
                              NULL, NULL );
         map_ptr = (int *) DXGetArrayData( map );


/*  Find all fields which have the same positions tag and the same data
 *  type. */

         tag = next->postag;
         dtype = next->datatype;

         nfld = 0;
         while( next ){

            if( next->postag == tag && next->datatype == dtype ){


/*  Increment the number of fields found so far which share this
 *  positions component. */

               nfld++;

               if( nfld > MAXFLD ){
                  DXSetError( ERROR_MAX, "\"input\" has too many fields.", MAXFLD );
                  goto error;
               }


/*  Store a pointer to the input data array, and its dimensionality. */

              indata[nfld-1] = (void *) DXGetArrayData( (Array) next->data );
              veclen[nfld-1] = next->datalen;


/*  Make a new array to hold the output data values. The output data will
 *  have the same dimensionality as the input data unless the required output
 *  data is "counts (i.e if parameter "type" is 2), in which case the
 *  output data will be scalar. */

              if( outtype == 2 ) veclen[nfld-1] = 1;

              outdata_array = DXNewArrayV( dtype, CATEGORY_REAL, 1, &veclen[nfld-1] );
              if( !outdata_array ) goto error;

              if( !DXAddArrayData( outdata_array, 0, nbin, NULL ) ) goto error;


/*  Get a pointer to the output data array. */

              outdata[nfld-1] = (void *) DXGetArrayData( outdata_array );
              if( !outdata[nfld-1] ) goto error;


/*  Place the new data component in the output field, and indicate that
 *  it now does not need to be deleted explicitly in the event of an error. */

              if( !DXSetComponentValue( next->outfld, "data", (Object) outdata_array ) ) goto error;
              outdata_array = NULL;

            }

            next = next->next;

         }


/*  Now bin the input data arrays into the output connections, storing the
 *  resulting bin values in the output data arrays. */

         if( dtype == TYPE_FLOAT ){
            if( ! SXBinF( nfld, veclen, npos, (float **)indata, nbin,
                          (float **) outdata, map_ptr, work, outtype,
                          outbad ) ) goto error;
         } else {
            if( ! SXBinD( nfld, veclen, npos, (double **)indata, nbin,
                          (double **) outdata, map_ptr, work, outtype,
                          outbad ) ) goto error;
         }


/*  Loop round all the fields that have just been created. */

         next = head;
         fld = 0;
         while( next ){
            if( next->postag == tag ){


/*  Create invalid positions components in each output field which have any
 *  undefined data values */

               if( outbad[fld] ){
                  if( dtype == TYPE_FLOAT ){
                     if( !SXSetInvPosF( (Object) next->outfld, nbin, veclen[fld],
                                        (float *) outdata[fld], "connections" ) ) goto error;
                  } else {
                     if( !SXSetInvPosD( (Object) next->outfld, nbin, veclen[fld],
                                        (double *) outdata[fld], "connections" ) ) goto error;
                  }
               }


/*  Indicate that the data values are dependant on connections. */

               if( !DXSetComponentAttribute( next->outfld, "data", "dep",
                                        (Object) DXNewString("connections")) ) goto error;


/*  Indicate that the data component of the output field has been
 *  changed. */

               DXChangedComponentValues( next->outfld, "data" );


/*  Complete the construction of this output field. */

               DXEndField( next->outfld );


/*  Increment the field index, and indicate that this input field has
 *  been done. */

               fld++;
               next->postag = 0;

            }

            next = next->next;

         }


/*  Delete the array used to store the reduced dimensionality input positions
 *  (if used). */

         if( a ) {
            DXDelete( (Object) a );
            a = NULL;
         }


      }

error:

/*  Free the storage used to hold the link list of Fpair structures
 *  describing the fields in the "input" object. */

      while( head ){
         next = head->next;
         DXFree( (Pointer) head );
         head = next;
      }


/*  Free the work array. */

      if( work ) DXFree( (Pointer) work );


/*  Delete the copy of the input and grid objects, and the array used to
 *  store the reduced dimensionality input positions (if used). */

      DXDelete( grid );
      DXDelete( input );
      if( a ) DXDelete( (Object) a );


/*  If all is OK, return the "output" object with a good status. */

      if( DXGetError() == ERROR_NONE ){
         out[0] = output;
         return( OK );


/*  If an error has occurred, ensure temporary objects are deleted and return
 *  with a bad status. */

      } else {
         DXDelete( (Object) outdata_array );
         DXDelete( output );
         return( ERROR );
      }

}
Пример #10
0
/* return outputs from module asynchronously
 */
Error DXSetOutputs(Object *olist, int dxfd)
{
    static int  firsttime = 1;
    Array	oarr;
    Error	ret    = ERROR;
    ErrorCode	ecode;
    Group	iobj	= NULL;
    Group	oobj	= NULL;
    Array	code	= NULL;
    String	mess	= NULL;
    int		i;
    int		count	= 0;
    int		one = 1;
    int         zero = 0;


    if (firsttime && ! callsetup (dxfd)) {
	host_status = HOST_CLOSED;
	return ERROR;
    }

	
    ecode = DXGetError();

    /*
     * Set up for return, at least the return code and message.
     */
    
    oobj = DXNewGroup ();
    if (oobj == NULL)
	goto finish_up;

    if (!(code = DXNewArray (TYPE_INT, CATEGORY_REAL, 0)))
	goto finish_up;

    if (! DXAddArrayData (code, 0, 1, (Pointer) &ecode))
	goto finish_up;

    mess = DXNewString (DXGetErrorMessage ());
    if (mess == NULL)
	goto finish_up;

    if (! DXSetEnumeratedMember (oobj, 0, (Object) code) ||
	! DXSetEnumeratedMember (oobj, 1, (Object) mess))
	goto finish_up;

    /*
     * If everything is OK then go ahead and return any objects too.
     */

    if (ecode == ERROR_NONE)
    {
	/* send output list so the caller can tell which outputs
	 * were set.  only send the non-NULL ones.
	 */
	oarr = DXNewArray(TYPE_INT, CATEGORY_REAL, 0);
	if (!oarr)
	    goto finish_up;
	for (i = 0; i < number_of_outputs; i++) {
	    if (! DXAddArrayData(oarr, i, 1, (olist+i) ? 
                                 (Pointer)&one : (Pointer)&zero))
		goto finish_up;
	}
	
	if (! DXSetEnumeratedMember(oobj, 2, (Object)oarr))
	    goto finish_up;
	

	count = 3;
        for (i = 0; i < number_of_outputs; i++)
        {
	    if (olist[i] == NULL)
		continue;

	    if (! DXSetEnumeratedMember (oobj, count++, olist[i]))
		goto finish_up;

	}
    }

    /* if the exec isn't already sitting there waiting for results,
     *  alert it that something is going to come back down the pipe,
     *  wait for it to be called and eat the new inputs, and send
     *  the new outputs.
     */
    if (!in_module) {
	DXInternalReadyToRun();
	
	iobj = (Group) _dxfImportBin_FP (dxfd);
	if (iobj == NULL)
	    goto finish_up;
	DXDelete ((Object)iobj);
    }

    if (!_dxfExportBin_FP ((Object)oobj, dxfd))
	goto finish_up;

    /* 
     * if you get to this point, there were no other errors.
     */
    ret = OK;


finish_up:

    /*
     * get rid of space not needed anymore.  this doesn't matter for
     * one-shots, but for persistent modules we will run out of memory
     * eventually if these aren't deleted.
     */
    DXDelete ((Object) oobj);
    in_module = 0;

    return ret;
}
Пример #11
0
Error DXCallOutboard (PFE m, int dxfd)
{
    static int  firsttime = 1;
    Array	oarr;
    int		nin	= 0;
    int		nout	= 0;
    Object	*ilist = NULL;
    Object	*olist = NULL;
    Error	ret    = ERROR;
    Error	modret;
    ErrorCode	ecode;
    char        *emessptr = NULL;
    Group	iobj	= NULL;
    Group	oobj	= NULL;
    Array	code	= NULL;
    String	mess	= NULL;
    int		i;
    int		*iptr;
    int		count	= 0;
    int		one = 1;
    int         zero = 0;


    if (firsttime && ! callsetup (dxfd)) {
	host_status = HOST_CLOSED;
	return ERROR;
    }

	
    /*
     * Import the remote object, extract the number of inputs and outputs,
     * and rip them apart appropriately.  group members are: 
     * input parm count, 
     * input object list (the pointers values don't mean anything in this
     * address space; the interesting part is whether they are NULL or not),
     * the output parm count,
     * and then each input object which isn't null.
     */

    iobj = (Group) _dxfImportBin_FP(dxfd);
    if(iobj == NULL)
        goto finish_up;

    if (!DXExtractInteger (DXGetEnumeratedMember (iobj, 0, NULL), &nin))
	goto finish_up;

    ilist = (Object *) DXAllocateZero(sizeof (Object) * nin);
    if (!ilist)
	goto finish_up;
    
    iptr = (int *)DXGetArrayData((Array)DXGetEnumeratedMember (iobj, 1, NULL));

    if (!DXExtractInteger (DXGetEnumeratedMember (iobj, 2, NULL), &nout))
	goto finish_up;

    count = 3;
    for (i=0; i<nin; i++) 
    {
	if (iptr[i] == (int)NULL)
	    continue;

	ilist[i] = DXGetEnumeratedMember(iobj, count++, NULL);
    }

    olist = (Object *) DXAllocateZero(sizeof (Object) * nout);
    if (!olist)
	goto finish_up;

    /*
     * Call the module, and save the error code if set.
     */

    DXResetError();
    
    _dxd_exOutboard = TRUE;
    modret = m (ilist, olist);
    _dxd_exOutboard = FALSE;

    /*
     * get these now, before we do something else which overwrites them.
     */
    ecode = DXGetError ();
    emessptr = DXGetErrorMessage();

    /* 
     * now BEFORE we do anything which allocates memory or new objects
     * check the return objects for validity.  we saw a case where the
     * object being returned was deleted, and then the DXNewGroup() 
     * below got the exact same address allocated, so when we put the
     * group together we put a reference to the parent group into the
     * same group as a child.  bad things followed...
     *
     * (the two calls above to geterror & geterrormsg don't allocate anything;
     * they return a value & ptr to a static respectively)
     */
    for (i = 0; i < nout; i++) {
	if (olist[i] == NULL)
	    continue;

	switch (DXGetObjectClass(olist[i])) {
	  case CLASS_DELETED:
	  case CLASS_MIN:
	  case CLASS_MAX:
	    if (ecode == ERROR_NONE) {
		DXSetError(ERROR_BAD_CLASS, "bad object returned as output %d from outboard module", i);
		ecode = DXGetError ();
		emessptr = DXGetErrorMessage();
	    } else
		DXAddMessage("bad object returned as output %d from outboard module", i);

	    olist[i] = NULL;
	  default: /* Lots of other classes */
	    break;
	}
    }

    /*
     * Set up for return, at least the return code and message.
     */
    
    oobj = DXNewGroup ();
    if (oobj == NULL)
	goto finish_up;

    if (!(code = DXNewArray (TYPE_INT, CATEGORY_REAL, 0)))
	goto finish_up;

    if (! DXAddArrayData (code, 0, 1, (Pointer) &ecode))
	goto finish_up;

    mess = DXNewString (emessptr);
    if (mess == NULL)
	goto finish_up;

    if (! DXSetEnumeratedMember (oobj, 0, (Object) code) ||
	! DXSetEnumeratedMember (oobj, 1, (Object) mess))
	goto finish_up;

    /*
     * If everything is OK then go ahead and return any objects too.
     */

    if (modret == OK)
    {
	/* send output list so the caller can tell which outputs
	 * were set.  only send the non-NULL ones.
	 */
	oarr = DXNewArray(TYPE_INT, CATEGORY_REAL, 0);
	if (!oarr)
	    goto finish_up;
	for (i = 0; i < nout; i++) {
	    if (! DXAddArrayData(oarr, i, 1, (olist+i) ? 
                                 (Pointer)&one : (Pointer)&zero))
		goto finish_up;
	}
	
	if (! DXSetEnumeratedMember(oobj, 2, (Object)oarr))
	    goto finish_up;
	

	count = 3;
        for (i = 0; i < nout; i++)
        {
	    if (olist[i] == NULL)
		continue;

	    if (! DXSetEnumeratedMember (oobj, count++, olist[i]))
		goto finish_up;

	}
    }

    if (!_dxfExportBin_FP ((Object)oobj, dxfd))
	goto finish_up;

    /* 
     * if you get to this point, there were no other errors.
     */
    ret = OK;


finish_up:

    /*
     * get rid of space not needed anymore.  this doesn't matter for
     * one-shots, but for persistent modules we will run out of memory
     * eventually if these aren't deleted.
     */

    DXDelete ((Object) iobj);
    DXDelete ((Object) oobj);

    DXFree ((Pointer) ilist);
    DXFree ((Pointer) olist);

    return ret;
}