Files
sics/nxdataset.c
koennecke 9eca96b064 - Fixes to make SL6 work
- New NeXus libraries
- Added new raw binary transfer mode for mass data
- Added a check script option to configurable virtual motor


SKIPPED:
	psi/dumprot.c
	psi/make_gen
	psi/psi.c
	psi/rebin.c
	psi/sanslirebin.c
2012-03-29 08:41:05 +00:00

459 lines
12 KiB
C

/*
This is a module which implements the notion of a dataset. Its is
designed for the use with scripting languages.
copyright: GPL
Mark Koennecke, October 2002
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "nxdataset.h"
/*-----------------------------------------------------------------------*/
static int getTypeSize(int typecode){
switch(typecode){
case NX_FLOAT32:
case NX_INT32:
case NX_UINT32:
return 4;
break;
case NX_FLOAT64:
case NX_INT64:
case NX_UINT64:
return 8;
break;
case NX_INT16:
case NX_UINT16:
return 2;
break;
default:
return 1;
break;
}
}
/*-----------------------------------------------------------------------*/
pNXDS createNXDataset(int rank, int typecode, int64_t dim[]){
pNXDS pNew = NULL;
int64_t length;
int i;
pNew = (pNXDS)malloc(sizeof(NXDS));
if(pNew == NULL){
return NULL;
}
pNew->dim = (int64_t *)malloc(rank*sizeof(int64_t));
for(i = 0, length = 1; i < rank; i++){
length *= dim[i];
}
/* add +1 in case of string NULL termination */
pNew->u.ptr = malloc(length*getTypeSize(typecode)+1);
if(pNew->dim == NULL || pNew->u.ptr == NULL){
free(pNew);
return NULL;
}
pNew->rank = rank;
pNew->type = typecode;
pNew->format = NULL;
for(i = 0; i < rank; i++){
pNew->dim[i] = dim[i];
}
pNew->magic = MAGIC;
/* add +1 in case of string NULL termination - see above */
memset(pNew->u.ptr,0,length*getTypeSize(typecode)+1);
return pNew;
}
/*---------------------------------------------------------------------*/
pNXDS createTextNXDataset(char *name){
pNXDS pNew = NULL;
pNew = (pNXDS)malloc(sizeof(NXDS));
if(pNew == NULL){
return NULL;
}
pNew->dim = (int64_t *)malloc(sizeof(int64_t));
pNew->u.cPtr = strdup(name);
if(pNew->dim == NULL || pNew->u.ptr == NULL){
free(pNew);
return NULL;
}
pNew->rank = 1;
pNew->type = NX_CHAR;
pNew->magic = MAGIC;
pNew->dim[0] = strlen(name);
return pNew;
}
/*-----------------------------------------------------------------------*/
void dropNXDataset(pNXDS dataset){
if(dataset == NULL){
return;
}
if(dataset->magic != MAGIC){
return;
}
if(dataset->dim != NULL){
free(dataset->dim);
}
if(dataset->u.ptr != NULL){
free(dataset->u.ptr);
}
if(dataset->format != NULL){
free(dataset->format);
}
free(dataset);
}
/*-----------------------------------------------------------------------*/
int getNXDatasetRank(pNXDS dataset){
if(dataset == NULL){
return 0;
}
if(dataset->magic != MAGIC){
return 0;
}
return dataset->rank;
}
/*-----------------------------------------------------------------------*/
int getNXDatasetDim(pNXDS dataset, int which){
if(dataset == NULL){
return 0;
}
if(dataset->magic != MAGIC){
return 0;
}
if(which < 0 || which >= dataset->rank){
return 0;
}
return dataset->dim[which];
}
/*------------------------------------------------------------------------*/
int getNXDatasetType(pNXDS dataset){
if(dataset == NULL){
return 0;
}
if(dataset->magic != MAGIC){
return 0;
}
return dataset->type;
}
/*--------------------------------------------------------------------*/
int getNXDatasetLength(pNXDS dataset){
int length, i;
if(dataset == NULL){
return 0;
}
if(dataset->magic != MAGIC){
return 0;
}
length = dataset->dim[0];
for(i = 1; i < dataset->rank; i++){
length *= dataset->dim[i];
}
return length;
}
/*---------------------------------------------------------------------*/
int getNXDatasetByteLength(pNXDS dataset){
return getNXDatasetLength(dataset)*getTypeSize(dataset->type);
}
/*----------------------------------------------------------------------
This calculates an arbitray address in C storage order
-----------------------------------------------------------------------*/
static int64_t calculateAddress(pNXDS dataset, int64_t pos[]){
int64_t result, mult;
int i, j;
result = pos[dataset->rank - 1];
for(i = 0; i < dataset->rank -1; i++){
mult = 1;
for(j = dataset->rank -1; j > i; j--){
mult *= dataset->dim[j];
}
if(pos[i] < dataset->dim[i] && pos[i] > 0){
result += mult*pos[i];
}
}
return result;
}
/*-----------------------------------------------------------------------*/
double getNXDatasetValue(pNXDS dataset, int64_t pos[]){
int64_t address;
if(dataset == NULL){
return 0;
}
if(dataset->magic != MAGIC){
return 0;
}
address = calculateAddress(dataset,pos);
return getNXDatasetValueAt(dataset, address);
}
/*----------------------------------------------------------------------*/
double getNXDatasetValueAt(pNXDS dataset, int64_t address){
double value;
if(dataset == NULL){
return 0;
}
if(dataset->magic != MAGIC){
return 0;
}
switch(dataset->type){
case NX_FLOAT64:
value = dataset->u.dPtr[address];
break;
case NX_FLOAT32:
value = (double)dataset->u.fPtr[address];
break;
case NX_INT32:
case NX_UINT32:
value = (double)dataset->u.iPtr[address];
break;
case NX_INT64:
case NX_UINT64:
value = (double)dataset->u.lPtr[address];
break;
case NX_INT16:
case NX_UINT16:
value = (double)dataset->u.sPtr[address];
break;
default:
value = (double)dataset->u.cPtr[address];
break;
}
return value;
}
/*-----------------------------------------------------------------------*/
char *getNXDatasetText(pNXDS dataset){
char *resultBuffer = NULL;
int status = 1;
if(dataset == NULL){
return strdup("NULL");
}
if(dataset->magic != MAGIC){
return strdup("NULL");
}
if(dataset->rank > 1){
status = 0;
}
if(dataset->type == NX_FLOAT32 ||
dataset->type == NX_FLOAT64 ||
dataset->type == NX_INT32 ||
dataset->type == NX_UINT32 ||
dataset->type == NX_INT64 ||
dataset->type == NX_UINT64 ||
dataset->type == NX_INT16 ||
dataset->type == NX_UINT16 ) {
status = 0;
}
if(status == 0){
return strdup("NO type problem");
}else{
resultBuffer = (char *)malloc((dataset->dim[0]+10)*sizeof(char));
if(resultBuffer == NULL){
return strdup("NO Memory");
}
memset(resultBuffer,0,(dataset->dim[0]+10)*sizeof(char));
strncpy(resultBuffer,dataset->u.cPtr,dataset->dim[0]);
}
return resultBuffer;
}
/*----------------------------------------------------------------------*/
int putNXDatasetValue(pNXDS dataset, int64_t pos[], double value){
int64_t address;
if(dataset == NULL){
return 0;
}
if(dataset->magic != MAGIC){
return 0;
}
address = calculateAddress(dataset,pos);
return putNXDatasetValueAt(dataset,address,value);
}
/*---------------------------------------------------------------------*/
int putNXDatasetValueAt(pNXDS dataset, int64_t address, double value){
/*
this code is dangerous, it casts without checking the data range.
This may cause trouble in some cases
*/
switch(dataset->type){
case NX_FLOAT64:
dataset->u.dPtr[address] = value;
break;
case NX_FLOAT32:
dataset->u.fPtr[address] = (float)value;
break;
case NX_INT32:
case NX_UINT32:
dataset->u.iPtr[address] = (int)value;
break;
case NX_INT64:
case NX_UINT64:
dataset->u.lPtr[address] = (int64_t)value;
break;
case NX_INT16:
case NX_UINT16:
dataset->u.sPtr[address] = (short int)value;
break;
default:
dataset->u.cPtr[address] = (char)value;
break;
}
return 1;
}
/*----------------------------------------------------------------------
This is working recursively through the dimensions. When at the last:
actual copying takes place.
-----------------------------------------------------------------------*/
static void copyCutData(pNXDS source, pNXDS target, int64_t sourceDim[],
int64_t targetDim[], int64_t start[], int64_t end[], int dim)
{
int i, length;
double val;
targetDim[dim] = 0;
length = end[dim] - start[dim];
if (dim == source->rank - 1) {
for (i = 0; i < length; i++) {
sourceDim[dim] = start[dim] + i;
val = getNXDatasetValue(source, sourceDim);
targetDim[dim] = i;
putNXDatasetValue(target, targetDim, val);
}
} else {
for (i = 0; i < length; i++) {
sourceDim[dim] = start[dim] + i;
targetDim[dim] = i;
copyCutData(source, target, sourceDim, targetDim, start, end,
dim + 1);
}
}
}
/*-----------------------------------------------------------------------*/
pNXDS cutNXDataset(pNXDS source, int64_t start[], int64_t end[])
{
pNXDS result = NULL;
int64_t newDim[NX_MAXRANK], i;
int64_t sourceDim[NX_MAXRANK], targetDim[NX_MAXRANK];
for (i = 0; i < source->rank; i++) {
if (start[i] < 0 || end[i] > source->dim[i]) {
fprintf(stderr, "ERROR: invalid boundaries specified for cutting");
return NULL;
}
newDim[i] = end[i] - start[i];
if (newDim[i] <= 0) {
fprintf(stderr,
"ERROR: invalid cut limits specified for cutting dataset");
return NULL;
}
}
result = createNXDataset(source->rank, source->type, newDim);
if (result == NULL) {
fprintf(stderr, "ERROR: out of memory creating result dataset");
return NULL;
}
copyCutData(source, result, sourceDim, targetDim, start, end, 0);
return result;
}
/*----------------------------------------------------------------------
This recurses through all dimensions, thereby skipping the summed one.
At the end of the recursion the actual summing is performed.
----------------------------------------------------------------------*/
static void sumData(pNXDS source, pNXDS target, int64_t sourceDim[],
int64_t targetDim[], int targetDimCount, int dimNo,
int start, int end, int currentDim)
{
int i, length;
double val, sumVal;
/*
when we have recursed through all dimensions
we actually do the sums...
*/
if (currentDim == source->rank) {
length = end - start;
sumVal = getNXDatasetValue(target, targetDim);
for (i = 0; i < length; i++) {
sourceDim[dimNo] = start + i;
val = getNXDatasetValue(source, sourceDim);
sumVal += val;
}
putNXDatasetValue(target, targetDim, sumVal);
} else {
/*
jump over the summed dimension while recursing
through the dimensions
*/
if (currentDim == dimNo) {
sumData(source, target, sourceDim,
targetDim, targetDimCount,
dimNo, start, end, currentDim + 1);
} else {
/*
loop over all values of the non summed dimension
*/
for (i = 0; i < source->dim[currentDim]; i++) {
/*
the problem here is that we have to jump over the summed
dimension here. This why we have to maintain a separate
dimension count for the target array. Jumping is done
above.
*/
targetDim[targetDimCount] = i;
targetDimCount++;
sourceDim[currentDim] = i;
sumData(source, target, sourceDim, targetDim, targetDimCount,
dimNo, start, end, currentDim + 1);
targetDimCount--;
}
}
}
}
/*-----------------------------------------------------------------------*/
pNXDS sumNXDataset(pNXDS source, int dimNo, int start, int end)
{
int64_t newDim[NX_MAXRANK], targetDim[NX_MAXRANK], sourceDim[NX_MAXRANK];
pNXDS result = NULL;
int i, count;
if (dimNo < 0 || dimNo > source->rank - 1) {
fprintf(stderr, "ERROR: invalid dimension for summing requested");
return NULL;
}
/*
make result dataset with missing summed dimension
*/
for (i = 0, count = 0; i < source->rank; i++) {
if (i != dimNo) {
newDim[count] = source->dim[i];
count++;
}
}
result = createNXDataset(source->rank - 1, source->type, newDim);
if (result == NULL) {
fprintf(stderr, "ERROR: out of memory creating result dataset");
return NULL;
}
sumData(source, result, sourceDim, targetDim, 0, dimNo, start, end, 0);
return result;
}