/* gcc -fPIC -c urs_ext.c -I/usr/include/python2.5 -o urs_ext.o -Wall -O gcc -shared urs_ext.o -o urs_ext.so */ #include "Python.h" #include "Numeric/arrayobject.h" #include "math.h" #include #include #include #include "structure.h" #define MAX_FILE_NAME_LENGTH 128 #define NODATA 99.0 #define EPSILON 0.00001 #define DEBUG 0 #define POFFSET 5 //Number of site_params void fillDataArray(int, int, int, int, int *, int *, float *, int *, int *, float *); long getNumData(int*, int*, int); char isdata(float); void wrttxt(char *, float, int, float *, float, float, float, float, float, int, int, int); float** _read_mux2(int, char **, float *, double *, int); PyObject *read_mux2(PyObject *self, PyObject *args){ /*Read in mux 2 file Python call: read_mux2(numSrc,filenames,weights,file_params,write) NOTE: A Python int is equivalent to a C long A Python double corresponds to a C double */ PyObject *filenames; PyArrayObject *pyweights,*file_params; PyArrayObject *pydata; PyObject *fname; char **muxFileNameArray; float *weights; long numSrc; long write; float **cdata; int dimensions[2]; int nsta0; int nt; double dt; int i,j; int start_tstep; int finish_tstep; int it,time; int num_ts; // Convert Python arguments to C if (!PyArg_ParseTuple(args, "iOOOi", &numSrc,&filenames,&pyweights,&file_params,&write)) { PyErr_SetString(PyExc_RuntimeError, "Input arguments to read_mux2 failed"); return NULL; } if(!PyList_Check(filenames)) { PyErr_SetString(PyExc_TypeError, "get_first_elem expects a list"); return NULL; } if(PyList_Size(filenames) == 0){ PyErr_SetString(PyExc_ValueError, "empty lists not allowed"); return NULL; } if (pyweights->nd != 1 || pyweights->descr->type_num != PyArray_DOUBLE) { PyErr_SetString(PyExc_ValueError, "pyweights must be one-dimensional and of type double"); return NULL; } if(PyList_Size(filenames) != pyweights->dimensions[0]){ PyErr_SetString(PyExc_ValueError, "Must specify one weight for each filename"); return NULL; } muxFileNameArray = (char **) malloc((int)numSrc*sizeof(char *)); if (muxFileNameArray == NULL) { printf("ERROR: Memory for muxFileNameArray could not be allocated.\n"); exit(-1); } for (i=0;ind != 1 || file_params->descr->type_num != PyArray_DOUBLE) { PyErr_SetString(PyExc_ValueError, "file_params must be one-dimensional and of type double"); return NULL; } // Create array for weights which are passed to read_mux2 weights = (float *) malloc((int)numSrc*sizeof(float)); for (i=0;i<(int)numSrc;i++){ weights[i]=(float)(*(double *)(pyweights->data+i*pyweights->strides[0])); } // Read in mux2 data from file cdata=_read_mux2((int)numSrc,muxFileNameArray,weights,(double*)file_params->data,(int)write); // Allocate space for return vector nsta0=(int)*(double *) (file_params -> data+0*file_params->strides[0]); dt=*(double *) (file_params -> data+1*file_params->strides[0]); nt=(int)*(double *) (file_params -> data+2*file_params->strides[0]); // Find min and max start times of all gauges start_tstep=nt+1; finish_tstep=-1; for (i=0;i finish_tstep){ finish_tstep=(int)cdata[i][nt+4]; } } if ((start_tstep>nt) | (finish_tstep < 0)){ printf("ERROR: Gauge data has incorrect start and finsh times\n"); return NULL; } if (start_tstep>=finish_tstep){ printf("ERROR: Gauge data has non-postive_length\n"); return NULL; } num_ts=finish_tstep-start_tstep+1; dimensions[0]=nsta0; dimensions[1]=num_ts+POFFSET; pydata = (PyArrayObject *) PyArray_FromDims(2, dimensions, PyArray_DOUBLE); if(pydata == NULL){ printf("ERROR: Memory for pydata array could not be allocated.\n"); return NULL; } // Each gauge begins and ends recording at different times. When a gauge is // not recording but at least one other gauge is. Pad the non-recording gauge // array with zeros. for (i=0;i=start_tstep)&&(it+1<=finish_tstep)){ if (it+1>(int)cdata[i][nt+4]){ //This gauge has stopped recording but others are still recording *(double *) (pydata -> data+i*pydata->strides[0]+time*pydata->strides[1])=0.0; }else{ *(double *) (pydata -> data+i*pydata->strides[0]+time*pydata->strides[1])=cdata[i][it]; } time++; } } // Pass back lat,lon,elevation for (j=0; j data+i*pydata->strides[0]+(num_ts+j)*pydata->strides[1])=cdata[i][nt+j]; } } free(weights); free(muxFileNameArray); return PyArray_Return(pydata); } float** _read_mux2(int numSrc, char **muxFileNameArray, float *weights, double *params, int write) { FILE *fp; int nsta, nsta0, i, isrc, ista; struct tgsrwg *mytgs, *mytgs0; char *muxFileName; int istart, istop; int *fros, *lros; char susMuxFileName; float *muxData; long numData; int len_sts_data; float **sts_data; float *temp_sts_data; long int offset; /* Allocate space for the names and the weights and pointers to the data*/ /* Check that the input files have mux2 extension*/ susMuxFileName=0; for(isrc=0;isrc 1){ /* allocate space for tgsrwg for the other sources */ mytgs = (struct tgsrwg *)malloc( nsta0*sizeof(struct tgsrwg) ); } else { /* FIXME (JJ): What should happen in case the are no source files?*/ /* If we exit here, tests will break */ // fprintf(stderr, "No source file specified\n"); // exit(-1); } /* loop over remaining sources, check compatibility, and read them into *muxData */ for(isrc=1; isrc nst[ista]==-1 */ { /* gauge never started recording, or was outside of all grids, fill array with 0 */ for(it=0; it=nst[jsta]&&it+1<=nft[jsta]) offset++; /* deal with the tide gauge at hand */ if(it+1>=nst[ista]&&it+1<=nft[ista]) /* gauge is recording at this time */ { memcpy(data+it,muxData+offset,sizeof(float)); offset++; } else if (it+1=nst[jsta]&&it+1<=nft[jsta]) offset++; } if(last_it < nt - 1) /* the loop was exited early because the gauge had finished recording */ for(it=last_it+1; it < nt; it++) data[it] = NODATA; } } /* Burbidge: No "offset" is sent. Replace with max. Added grid_id */ void wrttxt( fname, dt, nt, x, beg, lat, lon, max, depth, grid_id, istart, istop ) char *fname; float dt, *x, beg, max, lat, lon, depth; int grid_id; int nt; int istart, istop; { int it; float t; FILE *fp; fp = fopen(fname,"w"); fprintf(fp,"> lat %g lon %g depth %g max %g start_time %g stop_time %g grid_id %d\n", lat, lon, depth, max, istart*dt, istop*dt, grid_id ); for(it=0;it