
#/*##########################################################################
   # Copyright (C) 2001-2013 European Synchrotron Radiation Facility
   #
   #              PyHST2
   #  European Synchrotron Radiation Facility, Grenoble,France
   #
   # PyHST2 is  developed at
   # the ESRF by the Scientific Software  staff.
   # Principal author for PyHST2: Alessandro Mirone.
   #
   # 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.
   #
   # PyHST2 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
   # PyHST2; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
   # Suite 330, Boston, MA 02111-1307, USA.
   #
   # PyHST2 follows the dual licensing model of Trolltech's Qt and Riverbank's PyQt
   # and cannot be used as a free plugin for a non-free program.
   #
   # Please contact the ESRF industrial unit (industry@esrf.fr) if this license
   # is a problem for you.
   #############################################################################*/

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include<string.h>
#include"edftools.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<unistd.h>
#include"CCspace.h"



#undef NDEBUG
#include<assert.h>


int byteorder ( void )
{ short int one = 1;
  int value;
  switch ((int) *(char *) &one) {
  case 1: value = LowByteFirst; break;
  case 0: value = HighByteFirst; break;
  default: fprintf(stderr,"Invalid byte order \n");
    exit(1);
  }
  return( value );
}

char trimma(char  **pos, char **pos2) {
  char  res;
  while(**pos==' ') (*pos)++;
  *pos2=*pos;
  while((**pos2) !=' ' && (**pos2)!=0 && (**pos2)!=';'        ) (*pos2)++;
  res=**pos2;
  **pos2=0;
  return res;
}

void    prereadEdfHeader( int *sizeImage ,
			  int *byteorder ,
			  int *datatype  ,
			  long int *hsize     ,
			  int *Dim_1     ,
			  int *Dim_2     ,
			  char *filename,
			  char *CUR_NAME,
			  float *current
			  ) {
  char * line = NULL;
  size_t len = 0;
  ssize_t read;
  char *pos, *c1, *c2, oldc, *pos2;
  char oldc2;

  FILE *file;

  *sizeImage =-1;
  *byteorder =-1;
  *datatype  =-1;

  *hsize=0;


  *current=1.0;
  
  file=fopen(filename, "r");
  if(!file) {
    fprintf(stderr, "error trying to open file filename %s in %s line %d\n", filename, __FILE__, __LINE__);
    exit(1);
  }
  int restrained = 0;
  while( (read=getline(&line, &len, file) )!=-1) {
    *hsize = (*hsize) + read;
    pos = strstr(line, "=" );
    if(pos) {
      c1=line;
      while(*c1==' ' && c1<pos) {
	c1++;
      }
      c2=pos;
      if( c2>c1) c2--;
      while(  c2>c1) {
	c2--;
	if(*c2 !=' ') {
	  c2++;
	  break;
	}
      }
      oldc=*c2;
      *c2=0;
      pos++;
      /* printf("in prereadEdfHeader analizzando %s\n", c1);
	 printf("che ha valore %s\n", pos); */

      oldc2=trimma(&pos, &pos2);

      if(strcmp(c1, "ByteOrder")==0) {
	if( strcmp(pos, "HighByteFirst" )==0) {
	  *byteorder = HighByteFirst;
	} else if( strcmp(pos, "LowByteFirst")==0   ) {
	  *byteorder = LowByteFirst;
	} else {
	  fprintf(stderr, " value for %s is %s and is not recognized in %s line %d reading %s\n", c1, pos, __FILE__, __LINE__ , filename);
	  exit(1);
	}
      }


      if( CUR_NAME) {
	if(strcmp(c1, CUR_NAME )==0) {
	  *current  = strtof ( pos , &pos2);
	  if(*pos2!=0) {
	    fprintf(stderr, " value for %s is %s and cannot be transofmed to float in %s line %d  reading %s\n", c1, pos, __FILE__, __LINE__ , filename);
	    exit(1);
	  }
	}	
      }
      
      if(strcmp(c1, "DataType")==0) {
	if( strcmp(pos, "UnsignedShort" )==0) {
	  *datatype  = UnsignedShort ;
	} else if( strcmp(pos, "FloatValue")==0  ||  strcmp(pos, "Float")==0  ) {
	  *datatype  = FloatValue ;
	} else if( strcmp(pos, "SignedInteger")==0   ) {
	  *datatype  = SignedInteger ;
	} else  {
	  fprintf(stderr, " value for %s is %s and is not recognized in %s line %d  reading %s \n", c1, pos, __FILE__, __LINE__ , filename);
	  exit(1);
	}
      }

      if(strcmp(c1, "Size")==0) {
	*sizeImage = strtol ( pos , &pos2, 10);
	if(*pos2!=0) {
	  fprintf(stderr, " value for %s is %s and cannot be transofmed to int in %s line %d  reading %s\n", c1, pos, __FILE__, __LINE__ , filename);
	  exit(1);
	}
      }

      if(strcmp(c1, "Dim_1")==0) {
	*Dim_1 = strtol ( pos , &pos2, 10);
	if(*pos2!=0) {
	  fprintf(stderr, " value for %s is %s and cannot be transofmed to int in %s line %d  reading %s\n", c1, pos, __FILE__, __LINE__ , filename);
	  exit(1);
	}
      }


      if(restrained==0 && strcmp(c1, "Dim_2")==0) {
	*Dim_2 = strtol ( pos , &pos2, 10);
	if(*pos2!=0) {
	  fprintf(stderr, " value for %s is %s and cannot be transofmed to int in %s line %d  reading %s\n", c1, pos, __FILE__, __LINE__ , filename);
	  exit(1);
	}
      }

      if( strcmp(c1, "Ori_2")==0) {
	*Dim_2 = strtol ( pos , &pos2, 10);
	if(*pos2!=0) {
	  fprintf(stderr, " value for %s is %s and cannot be transofmed to int in %s line %d  reading %s\n", c1, pos, __FILE__, __LINE__ , filename);
	  exit(1);
	}
	restrained=1;
      }

      *pos2=oldc2 ;
      *c2  =  oldc;
    }

    if( strstr(line,"}")  ) break;
  }
  fclose(file);
  free(line);

  if(
     *sizeImage ==-1 ||
     *byteorder ==-1 ||
     *datatype  ==-1 ||
     *hsize     ==-1 ||
     *Dim_1     ==-1 ||
     *Dim_2     ==-1
     ) {
    fprintf(stderr, " some needed header tags has not been found  in %s line %d  reading %s\n", __FILE__, __LINE__ , filename);
    fprintf(stderr, "  *sizeImage %d ,*byteorder %d , *datatype %d ,  *hsize %ld\n"   ,*sizeImage,*byteorder , *datatype,  *hsize  );
    exit(1);
  }
}
void    prereadEdfHeader_restrained(  int *start_2     ,
				      int *real_2     ,
				      char *filename
				      ) {
  char * line = NULL;
  size_t len = 0;
  ssize_t read;
  char *pos, *c1, *c2, oldc, *pos2;
  char oldc2;

  FILE *file;

  *start_2=-1;
  *real_2=-1;

  file=fopen(filename, "r");
  if(!file) {
    fprintf(stderr, "error trying to open file filename %s in %s line %d\n", filename, __FILE__, __LINE__);
    exit(1);
  }
  while( (read=getline(&line, &len, file) )!=-1) {
    pos = strstr(line, "=" );
    if(pos) {
      c1=line;
      while(*c1==' ' && c1<pos) {
	c1++;
      }
      c2=pos;
      if( c2>c1) c2--;
      while(  c2>c1) {
	c2--;
	if(*c2 !=' ') {
	  c2++;
	  break;
	}
      }
      oldc=*c2;
      *c2=0;
      pos++;
      /* printf("in prereadEdfHeader analizzando %s\n", c1);
	 printf("che ha valore %s\n", pos); */

      oldc2=trimma(&pos, &pos2);


      if(strcmp(c1, "Dim_2")==0) {
	*real_2 = strtol ( pos , &pos2, 10);
	if(*pos2!=0) {
	  fprintf(stderr, " value for %s is %s and cannot be transofmed to int in %s line %d  reading %s\n", c1, pos, __FILE__, __LINE__ , filename);
	  exit(1);
	}
      }

      if( strcmp(c1, "First_2")==0) {
	*start_2 = strtol ( pos , &pos2, 10);
	if(*pos2!=0) {
	  fprintf(stderr, " value for %s is %s and cannot be transofmed to int in %s line %d  reading %s\n", c1, pos, __FILE__, __LINE__ , filename);
	  exit(1);
	}
      }

      *pos2=oldc2 ;
      *c2  =  oldc;
    }

    if( strstr(line,"}")  ) break;
  }
  fclose(file);
  free(line);

  if(
     *real_2 ==-1 ||
     *start_2 ==-1
     ) {
    fprintf(stderr, " some needed header tags has not been found  in %s line %d  reading %s\n", __FILE__, __LINE__ , filename);
    fprintf(stderr, "  *real_2 %d ,*start_2 %d   \n"   ,*real_2,*start_2   );
    exit(1);
  }
}

void extended_fread(   char *ptr,      /* memory to write in */
                       int   size_of_block,
                       int ndims        ,
                       int *dims      ,
                       int  *strides    ,
                       FILE *stream  ) {
  int pos;
  int oldpos;
  int  count;

  int indexes[ndims];
  int i;
  int loop;
  int res;

  oldpos=0;
  pos=0;
  count = 0;
  /*
    printf("received\n");
    printf("block = %d\n",size_of_block);
    printf("ndims = %d\n",ndims);
    printf("dims = %d %d\n",dims[0],dims[1]);
    printf("strides = %d\n",strides[0]);

  */
  for(i=0; i<ndims; i++) {
    indexes[i]=0;
  }
  
  loop=ndims-1;
  indexes[ndims-1 ]=-1  ;
  pos=-strides[ndims-1];

  while(1) {
    if(indexes[loop]< dims[loop]-1 ) {
      indexes[loop]++;
      pos += strides[loop];
      for( i=loop+1; i<ndims; i++)  {
        pos -= indexes[i]*strides[i];
        indexes[i]=0;
      }
      res=fseek( stream, (pos-oldpos),  SEEK_CUR );
      if(res!=0) {
	/*    throw ErrorExtendedFread_fseek_failed();*/
	printf("Error 1/n");
        break;
      }
      
      res=fread (  ( (char * ) ptr) +(count)*size_of_block ,
                   size_of_block, 1,  stream );
      if(res!=1) {
	/*    throw ErrorExtendedFread_fseek_failed();*/
	printf("Error 2/n");
        break;
      }
      count++;
      
      oldpos = pos+ size_of_block;
      
      loop=ndims-1;
      /*      for(i=0 ; i< ndims; i++) {
              printf(" %d ", indexes[i] );
              }
              printf("\n");
      */
    }else {
      loop--;
    }
    if(loop==-1) {
      break;
    }
  }
}
	      

void read_data_from_h5( char * filename,
			char * dsname,
			int nproj,
			float *target   , // target_float
			long int pos0 ,  long int pos1 ,
			long int size0 , long int size1,
			int rotation_vertical,
			int binning,
			int multiplo,
			float threshold,
			float *bptr
			) {
  
  hid_t     file;                        /* handles */
  hid_t     dataset;
  hid_t     memspace;
  hid_t     dataspace;
  hsize_t   dimsm[3];                     /* dataset and chunk dimensions*/
  hsize_t   count[3];
  hsize_t   offset[3];
  hsize_t   count_out[3];
  hsize_t   offset_out[3];
  herr_t    status;
  int       rank ;

  hid_t     dataspace_current=-1;


  assert(binning==1);
  
  printf(" reading %s dataset %s at nproj %d \n", filename, dsname, nproj ) ; 
  
  file = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT);
  dataset = H5Dopen(file, dsname);


  hid_t  dataset_current = H5Dopen(file, "current");

  
  dataspace = H5Dget_space(dataset);
  rank      = H5Sget_simple_extent_ndims(dataspace);
  // assert(rank==3);
  
  hsize_t dims_out[rank];
  H5Sget_simple_extent_dims( dataspace , dims_out , NULL  );
    
  /*
   * descrive quale parte del dataset  leggo
   */

  if(multiplo) {
    assert(  nproj == 0     ) ; 
  }
  
  offset[0] = nproj;
  offset[1] = pos0;
  offset[2] = pos1;
  int v_span = 1;
  
  if(multiplo) {
    v_span  = dims_out[0] ;
  }


  count[0]  = v_span ;
  count[1]  = size0;
  count[2]  = size1;

  status = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, offset, NULL,
  			       count, NULL);
  assert(status>=0);

  
  /*
   * descrive la memoria su cui scrivo
   */
  dimsm[0] = v_span;
  dimsm[1] = size0;
  dimsm[2] = size1 ;
  memspace = H5Screate_simple( 3, dimsm, NULL);

  /*
   * descrive quale parte di memoria scrivo
   */
  offset_out[0] = 0;
  offset_out[1] = 0;
  offset_out[2] = 0;
  count_out[0]  = v_span; 
  count_out[1]  = size0;
  count_out[2]  = size1;
  status = H5Sselect_hyperslab(memspace, H5S_SELECT_SET, offset_out, NULL,
  			       count_out, NULL);
  assert(status>=0);

  /*
   * Read data from hyperslab in the file into the hyperslab in
   * memory and display.
   */

  float *mytarget;
  if(v_span > 1) {
    mytarget = (float *) malloc(  v_span*size0*size1*  sizeof(float)) ; 
  } else {
    mytarget = target;
  }
  
  status = H5Dread(dataset,   H5T_NATIVE_FLOAT, memspace, dataspace,
  		   H5P_DEFAULT, mytarget);
  assert(status>=0);
  


  if(bptr) {
    int iz;
    for(iz=0; iz < v_span; iz++) {
      int k;
      for( k=0; k< size0*size1 ; k++ ) {
	mytarget[k+iz*size0*size1] = (mytarget[k+iz*size0*size1] - bptr[k + pos0*size1   ]) ; 
      }
    }
  }
  
  
  if(dataset_current>=0) {
    hid_t     dataspace_current  = H5Dget_space(dataset_current);
    hid_t     memspace_current;
    
    int myoffset = nproj ;
    int mycount = v_span;
    float currents[v_span] ;
    
    status = H5Sselect_hyperslab  (dataspace_current, H5S_SELECT_SET, &myoffset, NULL,   &mycount, NULL);
    memspace_current = H5Screate_simple (1, &mycount, NULL);
    status = H5Sselect_hyperslab  (memspace_current, H5S_SELECT_SET, &myoffset, NULL,   &mycount, NULL);
    status = H5Dread (dataset_current,  H5T_NATIVE_FLOAT , memspace_current, dataspace_current,  H5P_DEFAULT, v_span);
    
    status = H5Sclose (memspace_current);
    status = H5Sclose (dataspace_current);
    
    int iz ;
    for(iz=0; iz<v_span; iz++) {
      int k;      
      for( k=0; k< size0*size1 ; k++ ) {
	mytarget[k+ iz*size0*size1] = mytarget[k+ iz*size0*size1] / currents[iz] ; 
      }
    }
  }
  

  if(v_span > 1) {
    int i,k;
#pragma	omp parallel for  private(i,k) num_threads (8)
    for( i = 0; i<  size0*size1; i++) {
      float line[v_span];
      for(  k  =  0  ;  k <  v_span ;   k++  ) {
	line[ k ] = mytarget[  i + k * size0*size1    ] ;
      }
      target[  i  ] = quickselect(line, 0, v_span -(v_span%2), (v_span -(v_span%2) -1 )/2  );
    }
    if(threshold) {
      CCD_Filter_Implementation( mytarget, target , size0 , size1 ,threshold , 1);
      memcpy(  target,  mytarget, sizeof(float)*size0*size1   ) ; 
    }
    free( mytarget ) ;
  } else {
  }

  if(dataset_current >= 0) H5Dclose(dataset_current);
  H5Dclose(dataset);
  H5Sclose(dataspace);
  H5Sclose(memspace);
  H5Fclose(file);
  
  
}

void read_data_from_h5_eli( char * filename,
			    char * dsname,
			    int nproj,
			    float *target   , // target_float
			    long int pos0 ,  long int pos1 ,
			    long int size0 , long int size1,
			    int rotation_vertical,
			    int binning,
			    
			    float DZPERPROJ,
			    float *Ddark,
			    int correct_ff,
			    float *ff_infos,
			    float **FFs,
			    int doubleffcorrection,
			    int takelog,
			    float *ffcorr,
			    hid_t     *file,      
			    hid_t     *dataset,
			    hid_t *dataset_current
			    ) {
  
  assert(binning==1);
  
  long int i, j  ;
  
  /* int dims[1],strides[1]; */
  /* FILE *edffile; */
  /* int res; */
  
  for(i=0; i < size0; i++){
    for(j=0; j <  size1; j++){
      target[i*size1+j]= NAN ;
    }
  }
  
  hid_t     memspace;
  hid_t     dataspace;
  hsize_t   dimsm[3];                     /* dataset and chunk dimensions*/
  hsize_t   count[3];
  hsize_t   offset[3];
  hsize_t   count_out[3];
  hsize_t   offset_out[3];
  herr_t    status;
  int       rank ;
  

  
  float shift = nproj * DZPERPROJ;
  int ishift  = ((int) shift);
  shift = shift-ishift;   // si assume dzperproj sempre positivo
  pos0 = pos0  -ishift    ;
  int pos0_ = pos0-1;
  
  // int pos0_clipped=pos0;
  // if(pos0<0) pos0_clipped=0;
  
  int pos0_clipped_ = pos0_;
  if(pos0_<0) pos0_clipped_=0;
  int size0_clipped = size0;
  if((size0_clipped + pos0) > size1 ) {
    size0_clipped = size1 - pos0;
  }
  int size0_clipped_ =  size0_clipped+ 1  ;
  
  if(    pos0_ + size0_clipped_ >= pos0_clipped_ ) {
    
    printf(" reading %s dataset %s at nproj %d \n", filename, dsname, nproj ) ; 
    
    if(*file<0) {
      *file = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT);
      *dataset = H5Dopen(*file, dsname);
      *dataset_current = H5Dopen(*file, "current");
    }

    hid_t   dataspace_current=-1;

    dataspace = H5Dget_space(*dataset);
    rank      = H5Sget_simple_extent_ndims(dataspace);
    assert(rank==3);


    
    hsize_t dims_out[rank];
    H5Sget_simple_extent_dims( dataspace , dims_out , NULL  );
    
    /*
     * descrive quale parte del dataset  leggo
     */
    
    
    offset[0] = nproj;
    offset[1] = pos0_clipped_;
    offset[2] = pos1;
    int v_span = 1;
    
    
    
    count[0]  = v_span ;
    count[1]  = size0_clipped_-(pos0_clipped_-pos0_) ;
    count[2]  = size1;
    
    status = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, offset, NULL,
				 count, NULL);
    assert(status>=0);
    
    /*
     * descrive la memoria su cui scrivo
     */
    
    
    dimsm[0] = v_span;
    dimsm[1] =  size0_clipped_-(pos0_clipped_-pos0_);
    dimsm[2] = size1 ;
    memspace = H5Screate_simple( 3, dimsm, NULL);
    
    /*
     * descrive quale parte di memoria scrivo
     */
    offset_out[0] = 0;
    offset_out[1] = 0;
    offset_out[2] = 0;
    count_out[0]  = v_span; 
    count_out[1]  = size0_clipped_-(pos0_clipped_-pos0_);
    count_out[2]  = size1;
    status = H5Sselect_hyperslab(memspace, H5S_SELECT_SET, offset_out, NULL,
				 count_out, NULL);
    assert(status>=0);

    /*
     * Read data from hyperslab in the file into the hyperslab in
     * memory and display.
     */
    
    float *mytarget;
    mytarget = (float *) malloc(  v_span*( size0_clipped_  )*size1*  sizeof(float)) ; 
    
    status = H5Dread(*dataset,   H5T_NATIVE_FLOAT, memspace, dataspace,
		     H5P_DEFAULT, mytarget  +(pos0_clipped_-pos0_)*size1    );
    assert(status>=0);

    H5Sclose(dataspace);
    H5Sclose(memspace);
    
    if(pos0_clipped_-pos0_)  {
      memset( mytarget , 0,  (pos0_clipped_-pos0_)* sizeof(float) *((long int)   size1) );
    }
    
    for(j=0; j< size0_clipped_ ; j++){
      for(i=0; i< size1 ; i++){
	if((j+pos0_)>=0) {
	  
	  if(Ddark) {
	    mytarget [ j*size1+i ] =  (mytarget[j*size1+i ] - Ddark[(j+pos0_)*size1+i]) ;
	  }
	  
	  if(correct_ff)  {
	    float deno=1;
	    if(ff_infos[0]!=-1.0f) {
	      deno = FFs[0][ (j+pos0_)*size1+i] ;
	    }
	    if(ff_infos[1]!=-1.0f) {
	      deno = FFs[1][ (j+pos0_)*size1+i]*ff_infos[3]  + ff_infos[2]*deno ;
	    }
	    mytarget[j*size1+i ]  /= deno;
	  }
	}
      }
    }
    if(*dataset_current>=0) {
      hid_t     dataspace_current  = H5Dget_space(*dataset_current);
      hid_t     memspace_current;
      
      int myoffset = offset[0] ;
      int mycount = v_span;
      float currents[v_span] ;
      
      status = H5Sselect_hyperslab  (dataspace_current, H5S_SELECT_SET, &myoffset, NULL,   &mycount, NULL);
      memspace_current = H5Screate_simple (1, &mycount, NULL);
      status = H5Sselect_hyperslab  (memspace_current, H5S_SELECT_SET, &myoffset, NULL,   &mycount, NULL);
      status = H5Dread (*dataset_current,  H5T_NATIVE_FLOAT , memspace_current, dataspace_current,  H5P_DEFAULT, v_span);
      
      status = H5Sclose (memspace_current);
      status = H5Sclose (dataspace_current);
      
      int iz ;
      for(iz=0; iz<v_span; iz++) {
	int k;      
	for( k=0; k< size0_clipped*size1 ; k++ ) {
	  mytarget[k+ iz*size0_clipped*size1] = mytarget[k+ iz*size0_clipped*size1] / currents[iz] ; 
	}
      }
    }
    
    
    if(doubleffcorrection)    {
      if(takelog )    {
	for(j=0; j<size0; j++) {
	  for(i=0; i< size1; i++) {
	    if((j+pos0_)>=0) mytarget[j*size1+i ] *=     ffcorr[(j+pos0_)*size1+i] ;
	  }
	}
      } else {
	for(j=0; j<size0; j++) {
	  for(i=0; i< size1; i++) {
	    if((j+pos0_)>=0) mytarget[j*size1+i ] -=     ffcorr[(j+pos0_)*size1+i] ;
	  }
	}
      }
    }
    if(  rotation_vertical==0 ) {
      printf("MISSING FEATURE:  helicoidal scan with horizontal axis not yet implemented\n");// da rivedere accuratamente
      fprintf(stderr, "MISSING FEATURE:  helicoidal scan with horizontal axis not yet implemented \n");
    }
    for(j=0; j< (pos0_clipped_-pos0_); j++){
      for(i=0; i< size1; i++){
	mytarget[j*size1+i]=  NAN;
      }
    }
    for(i=pos0; i < pos0  + size0_clipped  ; i++){
      for(j=0; j <  size1; j++){
	target[(i-pos0)*size1+j]=  mytarget[ (i-pos0_) * size1 + j ] *(1-shift) + shift*   mytarget[ (i-pos0_-1) * size1 + j ]   ;
      }
    }
  } else {
  }

}



void read_projSequence_from_h5( char * filename,
				char * dsname,
				int Ninterval,
				int *nproj_intervals,
				float *target   , // target_float
				long int pos0 ,  long int pos1 ,
				long int size0 , long int size1,
				int rotation_vertical,
				int binning,
				hid_t *file,
				hid_t *dataset,
				hid_t *dataset_current,
				float *bptr
				) {
  
  /* hid_t     file;                        /\* handles *\/ */
  /* hid_t     dataset; */
  hid_t     memspace;
  hid_t     memspace_current;
  hid_t     dataspace;
  hid_t     dataspace_current;
  hsize_t   dimsm[3];                     /* dataset and chunk dimensions*/
  hsize_t   count[3];
  hsize_t   offset[3];
  hsize_t   count_out[3];
  hsize_t   offset_out[3];
  herr_t    status;
  int       rank ;


  if(*file==-1)  {
    *file = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT);
    *dataset = H5Dopen(*file, dsname);
    *dataset_current = H5Dopen(*file, "current");
  }
  
  dataspace = H5Dget_space(*dataset);
  rank      = H5Sget_simple_extent_ndims(dataspace);
  assert(rank==3);

  
  hsize_t dims_out[rank];
  H5Sget_simple_extent_dims( dataspace , dims_out , NULL  );
    

  int Ntot=0;
  int iv ;

  for(iv=0; iv <Ninterval; iv++) {


    
    offset[0] = nproj_intervals[2*iv];

    int  v_span =  nproj_intervals[ 2*iv+1 ] - nproj_intervals[ 2*iv ];

    printf(" Reading %d projections starting at %ld\n", v_span, (long int) offset[0] ) ;
    
    offset[1] = pos0;
    offset[2] = pos1;
    
    
    count[0]  = v_span ;
    count[1]  = size0;
    count[2]  = size1;
    
    status = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, offset, NULL,
				 count, NULL);
    assert(status>=0);

    /*
     * descrive la memoria su cui scrivo
     */
    dimsm[0] = v_span;
    dimsm[1] = size0;
    dimsm[2] = size1 ;
    memspace = H5Screate_simple( 3, dimsm, NULL);
    
    /*
     * descrive quale parte di memoria scrivo
     */
    offset_out[0] = 0;
    offset_out[1] = 0;
    offset_out[2] = 0;
    count_out[0]  = v_span; 
    count_out[1]  = size0;
    count_out[2]  = size1;
    status = H5Sselect_hyperslab(memspace, H5S_SELECT_SET, offset_out, NULL,
				 count_out, NULL);
    assert(status>=0);

    /*
     * Read data from hyperslab in the file into the hyperslab in
     * memory and display.
     */
    
    
    status = H5Dread(*dataset,   H5T_NATIVE_FLOAT, memspace, dataspace,
		     H5P_DEFAULT, target + Ntot*size0*size1 );
    
    assert(status>=0);

    if(bptr) {
      int iz ;
      for(iz=0; iz<v_span; iz++) {
	int k;      
	long int zoff =  (Ntot+iz)*size0*size1; 
	for( k=0; k< size0*size1 ; k++ ) {
	  target[k+zoff] = (target[k+ zoff] - bptr[k+pos0*size1]) ; 
	}
      }
    }
    
    if(*dataset_current>=0) {
      dataspace_current = H5Dget_space(*dataset_current);

      int myoffset = offset[0] ;
      int mycount = v_span;
      float currents[v_span] ; 
	
      status = H5Sselect_hyperslab  (dataspace_current, H5S_SELECT_SET, &myoffset, NULL,   &mycount, NULL);
      memspace_current = H5Screate_simple (1, &mycount, NULL);
      status = H5Sselect_hyperslab  (memspace_current, H5S_SELECT_SET, &myoffset, NULL,   &mycount, NULL);
      status = H5Dread (dataset_current,  H5T_NATIVE_FLOAT , memspace_current, dataspace_current,  H5P_DEFAULT, v_span);

      status = H5Sclose (memspace_current);
      status = H5Sclose (dataspace_current);
      
      int iz ;
      for(iz=0; iz<v_span; iz++) {
	long int zoff =  (Ntot+iz)*size0*size1; 
	int k;      
	for( k=0; k< size0*size1 ; k++ ) {
	  target[k+zoff] = target[k+ zoff] / currents[iz] ; 
	}
      }
    }
    Ntot += v_span ; 
  }
  // H5Dclose(dataset);
  H5Sclose(dataspace);
  H5Sclose(memspace);
  //  H5Fclose(file);
  
}




void     read_data_from_edf( char * filename,
			     float *dataptr  , // target_float
			     char *buffer  ,   // work buffer
			     int filedatatype, //
			     int rotation_vertical,
			     long int  headerSize,
			     long int pos0 ,  long int pos1 ,
			     long int size0 , long int size1,
			     int sizeofdatatype,
			     int Dim_2, int Dim_1,
			     int filebyteorder,
			     int binning,
			     sem_t * semaforo_ptr
			     ) {
  char  *target;
  float * target_float ;
  long int i, j, nbytes, n1,n2, k,l;
  char bsw;
  int dims[1],strides[1];
  FILE *edffile;
  int res;

  // printf(" apro %s filedatatype %d sizeofdatatype %d  \n", filename, filedatatype  , sizeofdatatype );
  sem_wait( semaforo_ptr );
  
  edffile = fopen( filename  ,"r");
  if(edffile==NULL) {
    sem_post( semaforo_ptr );
    fprintf(stderr," error opening %s for reading \n", filename );
    exit(1);
  }
  if(filedatatype!= FloatValue  || binning > 1 ) {
    target=buffer;
  } else {
    target = ((char * )  dataptr ) ;  /* sizeofdatatype[ self->reading_infos.datatype] ;*/
  }
  target_float= dataptr  ;


  int pos0_clipped=pos0;
  if(pos0<0) pos0_clipped=0;

  int size0_clipped = size0;
  if((size0_clipped + pos0_clipped)*binning > Dim_2 ) {
    size0_clipped = Dim_2/binning - pos0_clipped;
  }

  if(rotation_vertical==1) {
    res=fseek(edffile ,
	      headerSize  + ((long int )(pos0_clipped * binning *(size1*binning) *sizeofdatatype)),
	      SEEK_SET );
    if(res!=0) {

      printf("  headerSize %ld sizeofdatatype  %d   size1 %ld binning %d    %ld \n", headerSize , sizeofdatatype  ,  size1 , binning ,  headerSize  + ((long int )(pos0_clipped *(size1*binning) *sizeofdatatype )));

      fprintf(stderr," error positioning cursor in file %s for reading a chunk\n", filename   );
      sem_post( semaforo_ptr );
      exit(1);
    }
    res=fread (  target   +      (pos0_clipped-pos0)* sizeofdatatype *((long int)   size1) *  binning*binning ,
		 binning*binning*size0_clipped  *size1 *sizeofdatatype,
		 1,
		 edffile
		 );
    if(res!=1) {
      fprintf(stderr," error reading a chunk fromfile %s   res was %d\n", filename  , res);
      sem_post( semaforo_ptr );
      exit(1);
    }
    /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX  */
  } else   if(rotation_vertical==0) {
    res=fseek(edffile ,
	      headerSize  + binning*pos0_clipped * sizeofdatatype ,
	      SEEK_SET );
    if(res!=0) {
      fprintf(stderr," error positioning cursor in file %s for reading a chunk ( rotation horizontal) \n", filename   );
      sem_post( semaforo_ptr );
      exit(1);
    }

    dims[0]=size1 * binning;
    strides[0] =     Dim_1 * sizeofdatatype * binning;
    extended_fread(   target +      (pos0_clipped-pos0)* sizeofdatatype *((long int)   size1) *  binning*binning,
		      size0_clipped * sizeofdatatype * binning,
		      1        ,
		      dims      ,
		      strides    ,
		      edffile  );
  } else {
    sem_post( semaforo_ptr );
    
    fprintf(stderr," ROTATION_VERTICAL MUST BE EITHER 1 or 0 . Was %d . Now stopping\n", rotation_vertical);
    exit(1);
  }
  fclose(edffile);
  sem_post( semaforo_ptr );
  
  if(pos0_clipped-pos0)   memset( target , 0,  (pos0_clipped-pos0)* sizeofdatatype *((long int)   size1) *  binning*binning      );
  if(size0-size0_clipped)  memset( target  + ( (pos0_clipped-pos0)+ size0_clipped) * sizeofdatatype *((long int)   size1) *  binning*binning ,
				   0,      (size0-size0_clipped)* sizeofdatatype *((long int)   size1) *  binning*binning      );
  
  
  if( filebyteorder != byteorder ()  ) {
    /* swappa */
    
    
    nbytes = size0*size1  * sizeofdatatype  * binning*binning;
    if(  filedatatype== FloatValue || filedatatype== SignedInteger   ) {
      for(i=0; i<nbytes; i+=4) {
	bsw = target[i];
	target[i]=target[i+3];
	target[i+3]=bsw ;
	
	bsw = target[i+1];
	target[i+1]=target[i+2];
	target[i+2]=bsw ;
	
      }
    } else {
      for(i=0; i<nbytes; i+=2) {
	bsw = target[i];
	target[i]=target[i+1];
	target[i+1]=bsw ;
      }
    }
  }

  if(binning>1) {
    n1 = size0 ;
    n2 = size1 ;
    if(  rotation_vertical==0 ) {
      n2 = size0 ;
      n1 = size1 ;
    }
    if(filedatatype == FloatValue  ) {
      for(j=0; j<n1; j++){
	for(i=0; i< n2; i++){
	  target_float[j*n2+i]=0.0;
	  for(k=j*binning; k<(j+1)*binning; k++) {
	    for(l=i*binning; l<(i+1)*binning; l++) {
	      target_float[j*n2+i] +=  ((float *)  buffer ) [k*n2*binning+l]; ;
	    }
	  }
	  target_float[j*n2+i] /= (binning*binning);
	}
      }
    } else  {

      for(j=0; j<n1; j++){
	for(i=0; i< n2; i++){
	  target_float[j*n2+i]=0.0;
	  for(k=j*binning; k<(j+1)*binning; k++) {
	    for(l=i*binning; l<(i+1)*binning; l++) {
	      if (filedatatype == UnsignedShort  )	      target_float[j*n2+i] +=  ((unsigned short *)  buffer ) [k*n2*binning+l]; 
	      if (filedatatype == SignedInteger  )	      target_float[j*n2+i] +=  ((int *)  buffer ) [k*n2*binning+l]; 
	    }
	  }
	  target_float[j*n2+i] /= (binning*binning);
	}
      }
    }
  } else {
    if(filedatatype!= FloatValue  ) {
      nbytes = size0*size1 ;
      for(i=0; i<nbytes; i++) {
	if (filedatatype == UnsignedShort  ) target_float[i] = *( ((unsigned short*) target ) +i) ;
	if (filedatatype == SignedInteger  )target_float[i] = *( ((int*) target ) +i) ;
      }
    }
  }
  if(  rotation_vertical==0 ) {
    /* trasponi */
    memcpy( buffer,    target_float,size0*size1*sizeof(float)  );

    for(i=0; i < size0; i++){
      for(j=0; j <  size1; j++){
	target_float[i*size1+j]= ((float *)  buffer ) [j*size0+i];
      }
    }
  }
}


void     read_data_from_edf_eli( char * filename,
				 float *target_float, // target_float
				 int filedatatype, //
				 int rotation_vertical,
				 long int  headerSize,
				 long int pos0 ,  long int pos1 ,
				 long int size0 , long int size1,
				 int sizeofdatatype,
				 int Dim_2, int Dim_1,
				 int filebyteorder,
				 int binning,
				 int iread,
				 float DZPERPROJ,
				 float *Ddark,
				 int correct_ff,
				 float *ff_infos,
				 float **FFs,
				 int doubleffcorrection,
				 int takelog,
				 float *ffcorr,
				 float *currents,
				 float curr,
				 sem_t * semaforo_ptr
				 ) {
  long int i, j, nbytes, n1,n2, k,l;
  char bsw;
  int dims[1],strides[1];
  FILE *edffile;
  int res;

  // float *bufferF = (float *) malloc((Dim_2+1)*Dim_1*sizeof(float)) ;
  // char *buffer  = (char *) malloc((Dim_2+1)*Dim_1*sizeof(float)) ;
  float *bufferF = (float *) malloc((size0+1)*Dim_1*sizeof(float)) ;
  char *buffer  = (char *) malloc((size0+1)*Dim_1*sizeof(float)) ;

  // printf(" apro %s filedatatype %d sizeofdatatype %d  \n", filename, filedatatype  , sizeofdatatype );

  sem_wait( semaforo_ptr );
  edffile = fopen( filename  ,"r");
  if(edffile==NULL) {
    sem_post( semaforo_ptr );
    fprintf(stderr," error opening %s for reading \n", filename );
    exit(1);
  }


  float shift = iread * DZPERPROJ/binning;
  // int ishift  = (shift==((int)shift) )?   ((int) shift):(((int) shift)+1);
  int ishift  = ((int) shift);
  shift = shift-ishift;   // si assume dzperproj sempre positivo

  pos0 = pos0  -ishift    ;
  int pos0_ = pos0-1;

  int pos0_clipped=pos0;
  if(pos0<0) pos0_clipped=0;

  int pos0_clipped_ = pos0_;
  if(pos0_<0) pos0_clipped_=0;

  int size0_clipped = size0;
  if((size0_clipped + pos0)*binning > Dim_2 ) {
    size0_clipped = Dim_2/binning - pos0;
  }
  int size0_clipped_ =  size0_clipped+ 1  ;

  // printf("  Dim_2  pos0_   pos0   size0_clipped  size0  %d %d %d %d %d  \n" , Dim_2 , pos0_  , pos0 ,  size0_clipped  ,size0  );

  if(    pos0_ + size0_clipped_ >= pos0_clipped_ ) {
    if(rotation_vertical==1) {
      //printf("DEBUG mi positziono %ld in %p\n",  ((long int )(pos0_clipped *(size1*binning) *sizeofdatatype)) , edffile );
      //printf("DEBUG mi positziono %d \n",  pos0_clipped_  );
      res=fseek(edffile ,
		headerSize  + ((long int )(pos0_clipped_ *binning*(size1*binning) *sizeofdatatype)),
		SEEK_SET );
      if(res!=0) {
	sem_post( semaforo_ptr );
	fprintf(stderr," error positioning cursor in file %s for reading a chunk\n", filename   );
	exit(1);
      }
      // printf("DEBUG pos0_clipped %d  pos0 %d  size0_clipped %d  size1 %d \n", pos0_clipped, pos0, size0_clipped, size1);
      // printf("DEBUG leggo  %ld \n", binning*binning*size0_clipped  *size1 *sizeofdatatype );
      // printf(" leggo %d %d %d \n",  pos0_clipped ,  size0_clipped_-(pos0_clipped_-pos0_) ,  Dim_2 ) ;
      res=fread (buffer   +      (pos0_clipped_-pos0_)* sizeofdatatype *((long int)   size1) *  binning*binning ,
		 binning*binning*( size0_clipped_-(pos0_clipped_-pos0_) ) *size1 *sizeofdatatype,
		 1,
		 edffile
		 );
      if(res!=1) {
	fprintf(stderr," error reading a chunk fromfile %s   res was %d\n", filename  , res);
	sem_post( semaforo_ptr );
	exit(1);
      }
      /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX  */
    } else   if(rotation_vertical==0) {
      res=fseek(edffile ,
		headerSize  + binning*pos0_clipped * sizeofdatatype ,
		SEEK_SET );
      if(res!=0) {
	sem_post( semaforo_ptr );
	fprintf(stderr," error positioning cursor in file %s for reading a chunk ( rotation horizontal) \n", filename   );
	exit(1);
      }
      
      dims[0]=size1 * binning;
      strides[0] =     Dim_1 * sizeofdatatype * binning;
      extended_fread(   buffer +      (pos0_clipped_-pos0_)* sizeofdatatype *((long int)   size1) *  binning*binning,
			(size0_clipped_-(pos0_clipped_-pos0_) )* sizeofdatatype * binning,
			1        ,
			dims      ,
			strides    ,
			edffile  );
    } else {
      fprintf(stderr," ROTATION_VERTICAL MUST BE EITHER 1 or 0 . Was %d . Now stopping\n", rotation_vertical);
      sem_post( semaforo_ptr );
      exit(1);
    }
    fclose(edffile);
    sem_post( semaforo_ptr );
  }
  // printf(" DEBUG 1 \n");
  if( filebyteorder != byteorder ()  ) {
    /* swappa */
    nbytes = size0_clipped_ * size1  * sizeofdatatype  * binning*binning;
    if(filedatatype== FloatValue   ) {
      for(i=0; i<nbytes; i+=4) {
	bsw = buffer[i];
	buffer[i]=buffer[i+3];
	buffer[i+3]=bsw ;
	bsw = buffer[i+1];
	buffer[i+1]=buffer[i+2];
	buffer[i+2]=bsw ;
      }
    } else {
      for(i=0; i<nbytes; i+=2) {
	bsw = buffer[i];
	buffer[i]=buffer[i+1];
	buffer[i+1]=bsw ;
      }
    }
  }
  
  if(pos0_clipped_-pos0_)  {
    memset( buffer , 0,  (pos0_clipped_-pos0_)* sizeofdatatype *((long int)   size1) *  binning*binning      );
  }
  
  /* if(size0-size0_clipped) { */
  /*   memset( buffer  + ( (pos0_clipped-pos0)+ size0_clipped) * sizeofdatatype *((long int)   size1) *  binning*binning , */
  /*        0,    (size0-size0_clipped)* sizeofdatatype *((long int)   size1) *  binning*binning      ); */
  /* } */
  
  n1 = size0_clipped_ ;
  n2 = size1 ;
  if(  rotation_vertical==0 ) {
    n2 = size0_clipped_ ;
    n1 = size1 ;
  }
  
  if(filedatatype == FloatValue  ) {
    for(j=0; j<n1*binning; j++){
      for(i=0; i< n2*binning; i++){
	bufferF[j*n2*binning+i ] =  ((float *)  buffer ) [j*n2*binning+i]; ;
      }
    }
  } else  {
    for(j=0; j<n1*binning; j++){
      for(i=0; i< n2*binning; i++){
	bufferF[j*n2*binning+i ] =  ((unsigned short *)  buffer ) [j*n2*binning+i]; ;
      }
    }
  }
  
  // printf(" DEBUG 2 \n");
  
  /* memcpy(  target_float,  bufferF,size0*size1*sizeof(float)   ); */
  /* return; */
  
  for(j=0; j<n1*binning; j++){
    for(i=0; i< n2*binning; i++){
      if((j+pos0_)>=0) {
	if(Ddark) {
	  bufferF[j*n2*binning+i ] =  (bufferF[j*n2*binning+i ] - Ddark[(j+pos0_)*Dim_1+i])/curr ;
	} else {
	  bufferF[j*n2*binning+i ] =  (bufferF[j*n2*binning+i ] )/ curr ; 
	}
	if(correct_ff)  {
	  float deno=1;
	  if(ff_infos[0]!=-1.0f) {
	    deno = FFs[0][ (j+pos0_)*Dim_1+i] ;
	  }
	  if(ff_infos[1]!=-1.0f) {
	    deno = FFs[1][ (j+pos0_)*Dim_1+i]*ff_infos[3]  + ff_infos[2]*deno ;
	  }
	  bufferF[j*n2*binning+i ]  /= deno;
	}
      }
    }
  }
  
  if(doubleffcorrection)    {
    if(takelog )    {
      for(j=0; j<n1*binning; j++) {
	for(i=0; i< n2*binning; i++) {
	  if((j+pos0_)>=0) bufferF[j*n2*binning+i ] *=     ffcorr[(j+pos0_)*Dim_1+i] ;
	}
      }
    } else {
      for(j=0; j<n1*binning; j++) {
	for(i=0; i< n2*binning; i++) {
	  if((j+pos0_)>=0) bufferF[j*n2*binning+i ] -=     ffcorr[(j+pos0_)*Dim_1+i] ;
	}
      }
    }
  }
  // printf(" DEBUG 3 \n");
  
  float * bufferFF = (float *) buffer ;
  if(binning>1) {
    for(j=0; j<n1; j++){
      {
	for(i=0; i< n2; i++){
	  bufferFF[j*n2+i]=0.0;
	  for(k=j*binning; k<(j+1)*binning; k++) {
	    for(l=i*binning; l<(i+1)*binning; l++) {
	      bufferFF[j*n2+i] += bufferF [k*n2*binning+l]; ;
	    }
	  }
	  bufferFF[j*n2+i] /= (binning*binning);
	}
      }
    }
  } else {
    nbytes = size0_clipped_*size1 ;
    for(i=0; i<nbytes; i++) {
      bufferFF[i] = bufferF [i] ;
    }
  }
  // printf(" DEBUG 31 \n");

  if(  rotation_vertical==0 ) {
    printf("MISSING FEATURE:  helicoidal scan with horizontal axis not yet implemented\n");// da rivedere accuratamente
    fprintf(stderr, "MISSING FEATURE:  helicoidal scan with horizontal axis not yet implemented \n");// da rivedere accuratamente
    /* /\* trasponi *\/ */
    /* memcpy( buffer,    target_float,size0*size1*sizeof(float)  ); */
    
    /* for(i=0; i < size0; i++){ */
    /*   for(j=0; j <  size1; j++){ */
    /*  target_float[i*size1+j]= ((float *)  buffer ) [j*size0+i]; */
    /*   } */
    /* } */
  }

  // printf(" DEBUG 4 \n");

  for(j=0; j< (pos0_clipped_-pos0_); j++){
    for(i=0; i< size1; i++){
      bufferFF[j*n2+i]=  NAN;
    }
  }


  for(i=0; i < size0; i++){
    for(j=0; j <  size1; j++){
      target_float[i*size1+j]= NAN ;
    }
  }


  for(i=pos0; i < pos0  + size0_clipped  ; i++){
    for(j=0; j <  size1; j++){

      target_float[(i-pos0)*size1+j]=  bufferFF[ (i-pos0_) * size1 + j ] *(1-shift) + shift*   bufferFF[ (i-pos0_-1) * size1 + j ]   ;

    }
  }

  free(bufferF);
  free(buffer);
}




void write_data_to_edf( float *SLICE, int num_y,int  num_x,    const char * nomeout ) {
  FILE *output = fopen(nomeout,"w") ;
  if(!output) {
    printf(" error opening output file for slice now stopping\n");
    fprintf(stderr, " error opening output file for slice now stopping\n");
    exit(1);
  }

  {
    char s[4000];
    int len,i;

    if( byteorder()== LowByteFirst ) {

      sprintf(s,"{\nHeaderID       = EH:000001:000000:000000 ;\nImage          = 1 ;\nEDF_HeaderSize = 1024 ;\nByteOrder = LowByteFirst ;\nSize = %ld ;\nDim_1 = %d ;\nDim_2 = %d ;\nDataType = Float ;\n",num_y*((long)num_x)*4,num_x,num_y);
    } else {
      sprintf(s,"{\nHeaderID        =  EH:000001:000000:000000 ;\nImage           =  1 ;\nEDF_HeaderSize = 1024 ;\nByteOrder = HighByteFirst ;\nSize = %ld ;\nDim_1 = %d ;\nDim_2 = %d ;\nDataType = Float ;\n",num_y*((long)num_x)*4,num_x,num_y);
    }
    len=strlen(s);
    fwrite(s,1,len,output);
    for(i=len; i<1022; i++) {
      fwrite(" ",1,1,output);
    }
    fwrite("}\n",1,2,output);
  }
  fwrite(SLICE , sizeof(float), num_y*num_x , output);
  fclose(output);
}
void write_data_to_edf_restrained( float *SLICE, int num_y,int  num_x,
				   int start_y, int real_num_y,
				   const char * nomeout ) {
  FILE *output = fopen(nomeout,"w") ;
  if(!output) {
    printf(" error opening output file for slice now stopping\n");
    fprintf(stderr, " error opening output file for slice now stopping\n");
    exit(1);
  }

  {
    char s[4000];
    int len,i;

    if( byteorder()== LowByteFirst ) {

      sprintf(s,"{\nHeaderID       = EH:000001:000000:000000 ;\nImage          = 1 ;\nEDF_HeaderSize = 1024 ;\nByteOrder = LowByteFirst ;\nSize = %ld ;\nDim_1 = %d ;\nDim_2 = %d ;\nDataType = Float ;\nFirst_2 = %d ;\nOri_2 = %d ;\n",real_num_y*((long)num_x)*4,num_x,real_num_y, start_y,   num_y );
    } else {
      sprintf(s,"{\nHeaderID        =  EH:000001:000000:000000 ;\nImage           =  1 ;\nEDF_HeaderSize = 1024 ;\nByteOrder = HighByteFirst ;\nSize = %ld ;\nDim_1 = %d ;\nDim_2 = %d ;\nDataType = Float ;\nFirst_2 = %d ;\nOri_2 = %d ;\n",real_num_y*((long)num_x)*4,num_x,real_num_y, start_y,   num_y );
    }
    len=strlen(s);
    fwrite(s,1,len,output);
    for(i=len; i<1022; i++) {
      fwrite(" ",1,1,output);
    }
    fwrite("}\n",1,2,output);
  }
  fwrite(SLICE , sizeof(float), real_num_y*num_x , output);
  fclose(output);
}


void write_add_data_to_edf( float *SLICE, int num_y,int  num_x, char * nomeout,
			    int firstline, int nlines) {
  int fd;
  fd = open(nomeout,  O_RDWR );
  if(fd==-1) {
    fprintf(stderr, " ERROR : could not open : %s  \n", nomeout );
    exit(0);
  }
  // printf( " per il file %s scrivo %d slices a partire da %d \n", nomeout, nlines,  firstline);

  float * dum = (float *) malloc(nlines*num_x*sizeof(float));
  lseek( fd  ,1024+ firstline*num_x*sizeof(float), SEEK_SET);
  ssize_t  res_read = read( fd, dum, nlines*num_x*sizeof(float)  );
  if(0) assert( res_read == (nlines*num_x*sizeof(float))  ) ;
  lseek( fd  ,1024+ firstline*num_x*sizeof(float), SEEK_SET);

  int i;
  for(i=0; i< nlines*num_x; i++) {
    dum[i]+=SLICE[i];
  }
  ssize_t   w_res = write(fd,dum,  nlines*num_x*sizeof(float)    );
  if(0) assert(  w_res == nlines*num_x*sizeof(float)  );
  close(fd);
  free(dum);
}
