source: branches/numpy/anuga/shallow_water/urs_ext.c @ 6451

Last change on this file since 6451 was 6304, checked in by rwilson, 15 years ago

Initial commit of numpy changes. Still a long way to go.

File size: 26.0 KB
Line 
1/*
2gcc -fPIC -c urs_ext.c -I/usr/include/python2.5 -o urs_ext.o -Wall -O
3gcc -shared urs_ext.o  -o urs_ext.so
4*/
5
6#include "Python.h"
7#include "numpy/arrayobject.h"
8#include "structure.h"
9#include "math.h"
10#include <stdio.h>
11#include <float.h>
12#include <time.h>
13
14#define MAX_FILE_NAME_LENGTH 128
15#define NODATA 99.0
16#define EPSILON  0.00001
17
18#define DEBUG 0
19
20#define POFFSET 5 //Number of site_params
21
22static int *fros=NULL;  // First recorded output step
23static int *lros=NULL;  // Last recorded output step
24static struct tgsrwg* mytgs0=NULL;
25
26static long numDataMax=0;
27
28
29/*The MUX file format
30
31
32 */
33
34
35
36/////////////////////////////////////////////////////////////////////////
37//Auxiliary functions
38void fillDataArray(int ista, int total_number_of_stations, int nt, int ig, int *nst, 
39                   int *nft, float *data, int *istart_p, 
40                   int *istop_p, float *muxData)
41{
42    int it, last_it, jsta;
43    long int offset=0;
44
45
46    last_it = -1;
47    /* Make arrays of starting and finishing time steps for the tide gauges */
48    /* and fill them from the file */
49
50    /* Update start and stop timesteps for this gauge */
51    if (nst[ista]!= -1)
52    {
53        if(*istart_p == -1)
54        {
55            *istart_p = nst[ista];
56        }
57        else
58        {
59            *istart_p = ((nst[ista] < *istart_p) ? nst[ista] : *istart_p);
60        }
61    }
62   
63    if (nft[ista] != -1)
64    {
65        if (*istop_p == -1)
66        {
67            *istop_p = nft[ista];
68        }
69        else
70        {
71            *istop_p = ((nft[ista] < *istop_p) ? nft[ista] : *istop_p);
72        }
73    }     
74   
75    if (ig == -1 || nst[ista] == -1) /* currently ig==-1 => nst[ista]==-1 */
76    {
77        /* gauge never started recording, or was outside of all grids,
78        fill array with 0 */
79        for(it = 0; it < nt; it++)
80        {
81            data[it] = 0.0;
82        }
83    }   
84    else
85    {
86        for(it = 0; it < nt; it++)
87        {
88            last_it = it;
89            /* skip t record of data block */
90            offset++;
91            /* skip records from earlier tide gauges */
92            for(jsta = 0; jsta < ista; jsta++)
93                if(it + 1 >= nst[jsta] && it + 1 <= nft[jsta])
94                    offset++;
95
96            /* deal with the tide gauge at hand */
97            if(it + 1 >= nst[ista] && it + 1 <= nft[ista])
98            {
99                /* gauge is recording at this time */
100                memcpy(data + it, muxData + offset, sizeof(float));
101               
102                //printf("%d: muxdata=%f\n", it, muxData[offset]);                     
103                //printf("data[%d]=%f, offset=%d\n", it, data[it], offset);         
104                offset++;
105            }
106            else if (it + 1 < nst[ista])
107            {
108                /* gauge has not yet started recording */
109                data[it] = 0.0;
110            }   
111            else
112                /* gauge has finished recording */
113            {
114                data[it] = NODATA;
115                break;
116            }
117
118            /* skip records from later tide gauges */
119            for(jsta = ista + 1; jsta < total_number_of_stations; jsta++)
120                if(it + 1 >= nst[jsta] && it+1 <= nft[jsta])
121                    offset++;
122        }
123
124        if(last_it < nt - 1)
125            /* the loop was exited early because the gauge had
126            finished recording */
127            for(it = last_it+1; it < nt; it++)
128                data[it] = NODATA;
129    }
130} 
131
132
133char isdata(float x)
134{
135    if(x < NODATA + EPSILON && NODATA < x + EPSILON)
136    {
137      return 0;
138    }
139    else
140    {
141      return 1; 
142    }
143}
144
145
146long getNumData(const int *fros, const int *lros, const int total_number_of_stations)
147/* calculates the number of data in the data block of a mux file */
148/* based on the first and last recorded output steps for each gauge */ 
149{
150    int ista, last_output_step;
151    long numData = 0;
152
153    last_output_step = 0;   
154    for(ista = 0; ista < total_number_of_stations; ista++)
155        if(*(fros + ista) != -1)
156        {
157            numData += *(lros + ista) - *(fros + ista) + 1;
158            last_output_step = (last_output_step < *(lros+ista) ? 
159                            *(lros+ista):last_output_step);
160        }   
161        numData += last_output_step*total_number_of_stations; /* these are the t records */
162        return numData;
163}
164
165/////////////////////////////////////////////////////////////////////////
166//Internal Functions
167int _read_mux2_headers(int numSrc, 
168                       char **muxFileNameArray, 
169                       int* total_number_of_stations,
170                       int* number_of_time_steps,
171                       double* delta_t,
172                       //long* numDataMax,
173                       int verbose)
174{
175    FILE *fp;
176    int numsta, i, j;
177    struct tgsrwg *mytgs=0;
178    char *muxFileName;                                                                 
179    char susMuxFileName;
180    long numData;
181    size_t elements_read; // fread return value
182    int block_size;
183
184    /* Allocate space for the names and the weights and pointers to the data*/
185
186    /* Check that the input files have mux2 extension*/
187    susMuxFileName = 0;
188    for(i = 0; i < numSrc; i++)
189    { 
190        muxFileName = muxFileNameArray[i];
191        if(!susMuxFileName && strcmp(muxFileName + strlen(muxFileName) - 4, 
192                     "mux2") != 0)
193        {
194            susMuxFileName = 1;
195            break;
196        }
197    }
198
199    if(susMuxFileName)
200    {
201        printf("\n**************************************************************************\n");
202        printf("   WARNING: This program operates only on multiplexed files in mux2 format\n"); 
203        printf("   At least one input file name does not end with mux2\n");
204        printf("   Check your results carefully!\n");
205        printf("**************************************************************************\n\n");
206    }   
207
208    if (verbose)
209    {
210        printf("Reading mux header information\n");
211    }
212
213    // Loop over all sources, read headers and check compatibility
214    for (i = 0; i < numSrc; i++)
215    {
216        muxFileName = muxFileNameArray[i];
217
218        // Open the mux file
219        if((fp = fopen(muxFileName, "r")) == NULL)
220        {
221            fprintf(stderr, "cannot open file %s\n", muxFileName);
222            return -1; 
223        }
224       
225        if (!i)
226        {
227            elements_read = fread(total_number_of_stations, sizeof(int), 1, fp);
228            if ((int) elements_read == 0 && ferror(fp)){
229              fprintf(stderr, "Error reading total number of stations\n");
230              return -2;
231            }
232       
233            fros = (int*) malloc(*total_number_of_stations*numSrc*sizeof(int)); 
234            lros = (int*) malloc(*total_number_of_stations*numSrc*sizeof(int));
235     
236            mytgs0 = (struct tgsrwg*) malloc(*total_number_of_stations*sizeof(struct tgsrwg));
237            mytgs = (struct tgsrwg*) malloc(*total_number_of_stations*sizeof(struct tgsrwg));
238
239            block_size = *total_number_of_stations*sizeof(struct tgsrwg);
240            elements_read = fread(mytgs0, block_size , 1, fp);
241            if ((int) elements_read == 0 && ferror(fp)){
242              fprintf(stderr, "Error reading mytgs0\n");
243              return -2;
244            }
245        }
246        else
247        {
248            // Check that the mux files are compatible
249            elements_read = fread(&numsta, sizeof(int), 1, fp);
250            if ((int) elements_read == 0 && ferror(fp)){
251              fprintf(stderr, "Error reading numsta\n");
252              return -2;
253            }
254           
255            if(numsta != *total_number_of_stations)
256            {
257                fprintf(stderr,"%s has different number of stations to %s\n", 
258                muxFileName, 
259                muxFileNameArray[0]);
260                fclose(fp);
261                return -1;   
262            }
263
264            block_size = numsta*sizeof(struct tgsrwg);
265            elements_read = fread(mytgs, block_size, 1, fp); 
266            if ((int) elements_read == 0 && ferror(fp)){
267              fprintf(stderr, "Error reading mgtgs\n");
268              return -2;
269            }       
270           
271           
272            for (j = 0; j < numsta; j++)
273            {
274                if (mytgs[j].dt != mytgs0[j].dt)
275                {
276                    fprintf(stderr, "%s has different sampling rate to %s\n", 
277                    muxFileName, 
278                    muxFileNameArray[0]);
279                    fclose(fp);
280                    return -1;           
281                }   
282                if (mytgs[j].nt != mytgs0[j].nt)
283                {
284                    fprintf(stderr, "%s has different series length to %s\n", 
285                    muxFileName, 
286                    muxFileNameArray[0]);
287                    fclose(fp);
288                    return -1;           
289                }
290
291                if (mytgs[j].nt != mytgs0[0].nt)
292                {
293                    printf("Station 0 has different series length to Station %d\n", j); 
294                }
295            }
296        }
297
298        /* Read the start and stop times for this source */
299        elements_read = fread(fros + i*(*total_number_of_stations), 
300                              *total_number_of_stations*sizeof(int), 1, fp);
301        if ((int) elements_read == 0 && ferror(fp)){
302          fprintf(stderr, "Error reading start times\n");
303          return -3;
304        }           
305                           
306                           
307        elements_read = fread(lros + i*(*total_number_of_stations), 
308                              *total_number_of_stations*sizeof(int), 1, fp);
309        if ((int) elements_read == 0 && ferror(fp)){
310          fprintf(stderr, "Error reading stop times\n");       
311          return -3;
312        }                     
313
314        /* Compute the size of the data block for this source */
315        numData = getNumData(fros + i*(*total_number_of_stations), 
316                             lros + i*(*total_number_of_stations), 
317                             (*total_number_of_stations));
318
319        /* Sanity check */
320        if (numData < 0)
321        {
322            fprintf(stderr,"Size of data block appears to be negative!\n");
323            return -1;       
324        }
325
326        if (numDataMax < numData)
327        {
328            numDataMax = numData;
329        }
330
331        fclose(fp);         
332    }
333
334   
335    // Store time resolution and number of timesteps   
336    // These are the same for all stations as tested above, so
337    // we take the first one.
338    *delta_t = (double)mytgs0[0].dt;
339    *number_of_time_steps = mytgs0[0].nt;
340
341    free(mytgs);
342
343    return 0; // Succesful execution
344}
345
346
347float** _read_mux2(int numSrc, 
348                   char **muxFileNameArray, 
349                   float *weights, 
350                   double *params, 
351                   int *number_of_stations,
352                   long *permutation,
353                   int verbose)
354{
355    FILE *fp;
356    int total_number_of_stations, i, isrc, ista, k;
357    char *muxFileName;
358    int istart=-1, istop=-1;
359    int number_of_selected_stations;
360    float *muxData=NULL; // Suppress warning
361    long numData;
362
363    int len_sts_data, error_code;
364    float **sts_data;
365    float *temp_sts_data;
366
367    long int offset;
368
369    int number_of_time_steps, N;
370    double delta_t;
371   
372    size_t elements_read;
373   
374    // Shorthands pointing to memory blocks for each source
375    int *fros_per_source=NULL;     
376    int *lros_per_source=NULL;         
377
378   
379    error_code = _read_mux2_headers(numSrc, 
380                                    muxFileNameArray, 
381                                    &total_number_of_stations,
382                                    &number_of_time_steps,
383                                    &delta_t,
384                                    verbose);
385    if (error_code != 0) {
386      printf("urs_ext.c: Internal function _read_mux2_headers failed: Error code = %d\n", 
387             error_code);
388     
389      return NULL;
390    }
391   
392
393    // Apply rule that an empty permutation file means 'take all stations'
394    // We could change this later by passing in None instead of the empty
395    // permutation.
396    number_of_selected_stations = *number_of_stations; 
397    if (number_of_selected_stations == 0)
398    {
399        number_of_selected_stations = total_number_of_stations; 
400   
401        // Return possibly updated number of stations
402        *number_of_stations = total_number_of_stations;     
403     
404        // Create the Identity permutation vector
405        permutation = (long *) malloc(number_of_selected_stations*sizeof(long));
406        for (i = 0; i < number_of_selected_stations; i++)
407        {
408            permutation[i] = (long) i; 
409        }
410    }
411   
412    // The params array is used only for passing data back to Python.
413    params[0] = (double) number_of_selected_stations;
414    params[1] = (double) delta_t;
415    params[2] = (double) number_of_time_steps;
416   
417   
418   
419    // Make array(s) to hold demuxed data for stations given in the
420    // permutation file
421    sts_data = (float**) malloc(number_of_selected_stations*sizeof(float*));
422    if (sts_data == NULL)
423    {
424        printf("ERROR: Memory for sts_data could not be allocated.\n");
425        return NULL;
426    }
427
428    // For each selected station, allocate space for its data
429    len_sts_data = number_of_time_steps + POFFSET; // Max length of each timeseries?
430    for (i = 0; i < number_of_selected_stations; i++)
431    {
432        // Initialise sts_data to zero
433        sts_data[i] = (float*) calloc(len_sts_data, sizeof(float));
434        if (sts_data[i] == NULL)
435        {
436            printf("ERROR: Memory for sts_data could not be allocated.\n");
437            return NULL;
438        }
439    }
440
441    temp_sts_data = (float*) calloc(len_sts_data, sizeof(float));
442
443    muxData = (float*) malloc(numDataMax*sizeof(float));
444   
445    // Loop over all sources
446    for (isrc = 0; isrc < numSrc; isrc++)
447    {
448   
449        // Shorthands to local memory
450        fros_per_source = (int*) fros + isrc*total_number_of_stations; 
451        lros_per_source = (int*) lros + isrc*total_number_of_stations;     
452           
453   
454        // Read in data block from mux2 file
455        muxFileName = muxFileNameArray[isrc];
456        if((fp = fopen(muxFileName, "r")) == NULL)
457        {
458            fprintf(stderr, "cannot open file %s\n", muxFileName);
459            return NULL;                   
460        }
461
462        if (verbose){
463            printf("Reading mux file %s\n", muxFileName);
464        }
465
466        offset = sizeof(int) + total_number_of_stations*(sizeof(struct tgsrwg) + 2*sizeof(int));
467        fseek(fp, offset, 0);
468
469        numData = getNumData(fros_per_source, 
470                             lros_per_source, 
471                             total_number_of_stations);
472                             
473                             
474                                     
475        elements_read = fread(muxData, ((int) numData)*sizeof(float), 1, fp); 
476        if ((int) elements_read == 0 && ferror(fp)) {
477          fprintf(stderr, "Error reading mux data\n");
478          return NULL;
479        }
480               
481        fclose(fp);
482       
483
484        // FIXME (Ole): This is where Nariman and Ole traced the platform dependent
485        // difference on 11 November 2008. We don't think the problem lies in the
486        // C code. Maybe it is a problem with the MUX files written by the unit test
487        // that fails on Windows but works OK on Linux. JJ's test on 17th November shows
488        // that as far as Python is concerned this file should be OK on both platforms.
489       
490       
491       
492        // These printouts are enough to show the problem when compared
493        // on the two platforms
494        //printf("\nRead %d elements, ", (int) numData);
495        //printf("muxdata[%d]=%f\n", 39, muxData[39]);         
496       
497       
498        /*
499        In Windows we get
500       
501        Read 85 elements, muxdata[39]=0.999574
502        Read 85 elements, muxdata[39]=-0.087599
503        Read 85 elements, muxdata[39]=-0.087599
504       
505       
506        In Linux we get (the correct)
507       
508        Read 85 elements, muxdata[39]=0.999574
509        Read 85 elements, muxdata[39]=-0.087599
510        Read 85 elements, muxdata[39]=1.490349
511        */
512       
513       
514       
515       
516       
517        // loop over stations present in the permutation array
518        //     use ista with mux data
519        //     use i with the processed data to be returned         
520        for(i = 0; i < number_of_selected_stations; i++)
521        {               
522   
523            ista = (int) permutation[i]; // Get global index into mux data 
524       
525            // fill the data0 array from the mux file, and weight it
526            fillDataArray(ista, 
527                          total_number_of_stations, 
528                          number_of_time_steps,
529                          mytgs0[ista].ig, // Grid number (if -1 fill with zeros)
530                          fros_per_source, 
531                          lros_per_source, 
532                          temp_sts_data, 
533                          &istart, 
534                          &istop, 
535                          muxData);
536
537            // Weight appropriately and add
538            for(k = 0; k < mytgs0[ista].nt; k++)
539            {
540                if((isdata(sts_data[i][k])) && isdata(temp_sts_data[k]))
541                {
542                    sts_data[i][k] += temp_sts_data[k] * weights[isrc];
543                }
544                else
545                {
546                    sts_data[i][k] = NODATA;
547                }
548                //printf("%d: temp_sts_data[%d]=%f\n", i, k, temp_sts_data[k]);     
549           
550            }
551           
552           
553            // Update metadata (e.g. start time and end time)
554            N = number_of_time_steps;
555           
556            if (isrc == 0) {
557                // Assign values for first source
558                sts_data[i][N] = (float)mytgs0[ista].geolat;
559                sts_data[i][N+1] = (float)mytgs0[ista].geolon;
560                sts_data[i][N+2] = (float)mytgs0[ista].z;
561                sts_data[i][N+3] = (float)fros_per_source[ista];
562                sts_data[i][N+4] = (float)lros_per_source[ista];
563            } else {
564                // Update first and last timesteps for subsequent sources
565                if (sts_data[i][N+3] > (float)fros_per_source[ista]) {         
566                    if (verbose) {
567                        printf("Adjusting start time for station %d and source %d",
568                               ista, isrc);
569                        printf(" from %f to %f\n", 
570                               sts_data[i][N+3], 
571                               (float) fros_per_source[ista]); 
572                    }
573                    sts_data[i][N+3] = (float) fros_per_source[ista];
574                }
575               
576                if (sts_data[i][N+4] < (float) lros_per_source[ista]) {         
577                    if (verbose) {
578                        printf("Adjusting end time for station %d and source %d",
579                               ista, isrc);
580                        printf(" from %f to %f\n", 
581                               sts_data[i][N+4], 
582                               (float) lros_per_source[ista]); 
583                    }
584                    sts_data[i][N+4] = (float) lros_per_source[ista];
585                }               
586            }
587        }
588    }
589
590    //printf("sts_data[1,8]=%f\n", sts_data[1][8]);
591   
592    free(muxData);
593    free(temp_sts_data);
594    free(fros);
595    free(lros);
596    free(mytgs0);
597
598    return sts_data;
599}
600
601/////////////////////////////////////////////////////////////////////////
602//Python gateways
603PyObject *read_mux2(PyObject *self, PyObject *args)
604{
605    /*Read in mux 2 file
606
607    Python call:
608    read_mux2(numSrc,filenames,weights,file_params,permutation,verbose)
609
610    NOTE:
611    A Python int is equivalent to a C long
612    (this becomes really important on 64 bit architectures)
613   
614    A Python double corresponds to a C double
615    */
616   
617    PyObject *filenames;
618    PyArrayObject *pyweights;
619    PyArrayObject *file_params;
620    PyArrayObject *permutation;  // Ordering of selected stations   
621    PyArrayObject *pydata;
622    PyObject *fname;
623
624    char **muxFileNameArray;
625    float **cdata;
626    float *weights;
627    int dimensions[2];
628    int numSrc;
629    int verbose;
630    int total_number_of_stations;
631    int number_of_selected_stations;   
632    int nt;
633    double dt;
634    int i;
635    int j;
636    int start_tstep;
637    int finish_tstep;
638    int it;
639    int time;
640    int num_ts;
641   
642    // Convert Python arguments to C
643    if (!PyArg_ParseTuple(args, "iOOOOi",
644              &numSrc, &filenames, &pyweights, &file_params, 
645              &permutation, &verbose)) 
646    {
647            PyErr_SetString(PyExc_RuntimeError, 
648                "Input arguments to read_mux2 failed");
649            return NULL;
650    }
651
652    if(!PyList_Check(filenames)) 
653    {
654        PyErr_SetString(PyExc_TypeError, "get_first_elem expects a list");
655        return NULL;
656    }
657
658    if(PyList_Size(filenames) == 0)
659    {
660        PyErr_SetString(PyExc_ValueError, "empty lists not allowed");
661        return NULL;
662    }
663
664    if (pyweights->nd != 1 || pyweights->descr->type_num != PyArray_DOUBLE) 
665    {
666        PyErr_SetString(PyExc_ValueError,
667            "pyweights must be one-dimensional and of type double");
668        return NULL; 
669    }
670
671    if(PyList_Size(filenames) != pyweights->dimensions[0])
672    {
673        PyErr_SetString(PyExc_ValueError, 
674            "Must specify one weight for each filename");
675        return NULL;
676    }
677
678    muxFileNameArray = (char**)malloc(numSrc*sizeof(char*));
679    if (muxFileNameArray == NULL) 
680    {
681        PyErr_SetString(PyExc_ValueError, 
682                        "ERROR: Memory for muxFileNameArray could not be allocated.");
683        return NULL;
684    }
685
686    for (i = 0; i < numSrc; i++)
687    {
688
689        fname = PyList_GetItem(filenames, i);
690        if (!fname) 
691        {
692            PyErr_SetString(PyExc_ValueError, "filename not a string");
693            return NULL;
694        }       
695
696        muxFileNameArray[i] = PyString_AsString(fname);
697        if (muxFileNameArray[i] == NULL) 
698        {
699            PyErr_SetString(PyExc_ValueError, 
700          "ERROR: Memory for muxFileNameArray could not be allocated.\n");
701            return NULL;
702        }
703    }
704
705    if (file_params->nd != 1 || file_params->descr->type_num != PyArray_DOUBLE) 
706    {
707        PyErr_SetString(PyExc_ValueError,
708          "file_params must be one-dimensional and of type double");
709        return NULL; 
710    }
711
712
713    // Create array for weights which are passed to read_mux2
714    weights = (float*) malloc(numSrc*sizeof(float));
715    for (i = 0; i < numSrc; i++)
716    {
717        weights[i] = (float)(*(double*)(pyweights->data + i*pyweights->strides[0]));
718    }
719   
720    // Desired number of stations
721    number_of_selected_stations = (int) permutation->dimensions[0];
722
723    // Read in mux2 data from file
724    cdata = _read_mux2(numSrc, 
725                       muxFileNameArray, 
726                       weights, 
727                       (double*)file_params->data,
728                       &number_of_selected_stations, 
729                       (long*) permutation->data,
730                       verbose);
731
732    if (!cdata) 
733    {
734        PyErr_SetString(PyExc_ValueError, "No STS_DATA returned");
735        return NULL;
736    }       
737               
738               
739    // Allocate space for return vector
740    total_number_of_stations = (int)*(double*)(file_params->data + 0*file_params->strides[0]);
741    dt = *(double*)(file_params->data + 1*file_params->strides[0]);
742    nt = (int)*(double*)(file_params->data + 2*file_params->strides[0]);
743
744   
745    // Find min and max start times of all gauges
746    start_tstep = nt + 1;
747    finish_tstep = -1;
748    for (i = 0; i < number_of_selected_stations; i++)
749    {
750        //printf("cdata[%d] start = %f\n", i, (double) cdata[i][nt+3]);
751        // printf("cdata[%d] finish = %f\n", i, (double) cdata[i][nt+4]);   
752   
753        if ((int)cdata[i][nt + 3] < start_tstep)
754        {
755            start_tstep = (int)cdata[i][nt + 3];
756        }
757        if ((int)cdata[i][nt + 4] > finish_tstep)
758        {
759            finish_tstep = (int)cdata[i][nt + 4]; 
760        }
761    }
762
763    if ((start_tstep > nt) | (finish_tstep < 0))
764    {
765        printf("ERROR: Gauge data has incorrect start and finish times:\n");
766        printf("   start_tstep = %d, max_number_of_steps = %d\n", 
767               start_tstep, nt);
768        printf("   finish_tstep = %d, min_number_of_steps = %d\n", 
769               finish_tstep, 0);   
770           
771        PyErr_SetString(PyExc_ValueError, "Incorrect start and finish times"); 
772        return NULL;
773    }
774
775    if (start_tstep >= finish_tstep)
776    {
777        PyErr_SetString(PyExc_ValueError,
778                    "ERROR: Gauge data has non-postive_length");
779        return NULL;
780    }
781
782    num_ts = finish_tstep - start_tstep + 1;
783    dimensions[0] = number_of_selected_stations;
784    dimensions[1] = num_ts + POFFSET;
785   
786    pydata = (PyArrayObject*) PyArray_FromDims(2, dimensions, PyArray_DOUBLE);
787    if(pydata == NULL)
788    {
789        PyErr_SetString(PyExc_ValueError, 
790          "ERROR: Memory for pydata array could not be allocated.");
791        return NULL;
792    }
793
794   
795    // Each gauge begins and ends recording at different times. When a gauge is
796    // not recording but at least one other gauge is.
797    // Pad the non-recording gauge array with zeros.
798    //printf("\nData put into the cdata array from C code\n");
799    for (i = 0; i < number_of_selected_stations; i++)
800    {
801        time = 0;
802        for (it = 0; it < finish_tstep; it++)
803        {
804            if ((it + 1 >= start_tstep) && (it + 1 <= finish_tstep))
805            {
806                if (it + 1 > (int)cdata[i][nt + 4])
807                {
808                    // This gauge has stopped recording but others are
809                    // still recording
810                    *(double*)(pydata->data + i*pydata->strides[0] 
811                               + time*pydata->strides[1]) = 
812                      0.0;
813                }
814                else
815                {
816                  //printf("cdata[%d][%d] = %f\n", i, it, cdata[i][it]);
817               
818                    *(double*)(pydata->data + i*pydata->strides[0] 
819                                    + time*pydata->strides[1]) = 
820                        cdata[i][it];
821                }
822                time++;
823            }
824        }
825        // Pass back lat,lon,elevation
826        for (j = 0; j < POFFSET; j++)
827        {
828          *(double*)(pydata->data + i*pydata->strides[0] 
829                     + (num_ts + j)*pydata->strides[1]) = 
830            cdata[i][nt + j];
831        }
832    }
833
834    free(weights);
835   
836    // Free filename array, but not independent Python strings
837    // FIXME(Ole): Do we need to update a reference counter in this case?
838    free(muxFileNameArray);
839   
840    for (i = 0; i < number_of_selected_stations; ++i)
841    {
842        free(cdata[i]);
843    }
844    free(cdata);
845
846    return PyArray_Return(pydata);
847}
848
849//-------------------------------
850// Method table for python module
851//-------------------------------
852static struct PyMethodDef MethodTable[] = {
853    {"read_mux2", read_mux2, METH_VARARGS, "Print out"},
854    {NULL, NULL}
855};
856
857// Module initialisation
858void initurs_ext(void){
859    Py_InitModule("urs_ext", MethodTable);
860
861    import_array(); // Necessary for handling of NumPY structures
862}
Note: See TracBrowser for help on using the repository browser.