/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * filename: m-matrix.h                                                    *
 *                                                                         *
 * UTIL C-source: Medical Image Conversion Utility                         *
 *                                                                         *
 * purpose      : m-matrix.c header file                                   *
 *                                                                         *
 * project      : (X)MedCon by Erik Nolf                                   *
 *                                                                         *
 * Notes        : Source code addapted from CTI PET Systems, Inc.          *
 *                Original code 2.2 10/19/93  Copyright 1989-1993          *
 *                                                                         *
 *                Changed code for swapping & the use of my data types     *
 *                with machine independency as purpose                     *
 *                                                                         *
 *                Added structs and prototypes for ECAT 7 reading support  *
 *                                                                         *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* $Id: m-matrix.h,v 1.25 2013/06/23 21:51:19 enlf Exp $
 */

/*
   Copyright (C) 1997-2013 by Erik Nolf

   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, 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.,
   59 Place - Suite 330, Boston, MA 02111-1307, USA.  */

#ifndef __M_MATRIX_H__
#define __M_MATRIX_H__

/****************************************************************************
                              D E F I N E S 
****************************************************************************/

#define MDC_ECAT6_MAX_MATRICES 5000

#define MdcMatBLKSIZE     512
#define MdcMatFirstDirBlk 2

#define MdcMatrixBlocks(x)   (((x+(MdcMatBLKSIZE-1))/MdcMatBLKSIZE)*MdcMatBLKSIZE);

struct Mdc_MatDir {
        Int32 matnum;
        Int32 strtblk;
        Int32 endblk;
        Int32 matstat;
};

typedef struct mdc_matdir {
        Int32 nmats;
        Int32 nmax;
        struct Mdc_MatDir *entry;
} *Mdc_Mat_dir;

struct Mdc_Matval {
        Int32 frame, plane, gate, data, bed;
};

/*
#define TotalCounts      0
#define UnknownCalib     TotalCounts + 1
#define MDC_ECAT_COUNTS  UnknownCalib + 1
#define MCi_ML           MDC_ECAT_COUNTS + 1
#define LmrGlu           MCi_ML + 1
#define LmrGlu_mMole     LmrGlu + 1
#define LmrGlu_mGram     LmrGlu_mMole + 1
#define NCi_ML           LmrGlu_mGram + 1
#define WELL_COUNTS      NCi_ML + 1
#define BECQUERELS       WELL_COUNTS + 1   
*/

typedef struct mdc_mat_main_header {
	char		original_file_name[20];
	Int16		sw_version;
	Int16		data_type;
	Int16		system_type;
	Int16		file_type;
	char		node_id[10];
	Int16		scan_start_day,
			scan_start_month,
			scan_start_year,
			scan_start_hour,
			scan_start_minute,
			scan_start_second;
	char		isotope_code[8];
	float		isotope_halflife;
	char		radiopharmaceutical[32];
	float		gantry_tilt,
			gantry_rotation,
			bed_elevation;
	Int16		rot_source_speed,
			wobble_speed,
			transm_source_type;
	float		axial_fov,
			transaxial_fov;
	Int16		transaxial_samp_mode,
			coin_samp_mode,
			axial_samp_mode;
	float		calibration_factor;
	Int16		calibration_units,
			compression_code;
	char		study_name[12],
			patient_id[16],
			patient_name[32],
			patient_sex,
			patient_age[10],
			patient_height[10],
			patient_weight[10],
			patient_dexterity,
			physician_name[32],
			operator_name[32],
			study_description[32];
	Int16		acquisition_type,
			bed_type,
			septa_type;
	char		facility_name[20];
	Int16		num_planes,
			num_frames,
			num_gates,
			num_bed_pos;
	float		init_bed_position,
			bed_offset[15],
			plane_separation;
	Int16		lwr_sctr_thres,
			lwr_true_thres,
			upr_true_thres;
	float		collimator;
	char		user_process_code[10];
	Int16		acquisition_mode;

} Mdc_Main_header;

#define MH_64_SIZE 446

typedef struct mdc_mat_main_header7 {

  char magic_number[14];
  char original_file_name[32];
  Int16 sw_version;
  Int16 system_type;
  Int16 file_type;
  char serial_number[10];
  Uint32 scan_start_time;
  char isotope_name[8];
  float isotope_halflife;
  char radiopharmaceutical[32];
  float gantry_tilt;
  float gantry_rotation;
  float bed_elevation;
  float intrinsic_tilt;
  Int16 wobble_speed;
  Int16 transm_source_type;
  float distance_scanned;
  float transaxial_fov;
  Int16 angular_compression;
  Int16 coin_samp_mode;
  Int16 axial_samp_mode;
  float ecat_calibration_factor;
  Int16 calibration_units;
  Int16 calibration_units_label;
  Int16 compression_code;
  char study_type[12];
  char patient_id[16];
  char patient_name[32];
  char patient_sex[1];
  char patient_dexterity[1];
  float patient_age;
  float patient_height;
  float patient_weight;
  Uint32 patient_birth_date;
  char physician_name[32];
  char operator_name[32];
  char study_description[32];
  Int16 acquisition_type;
  Int16 patient_orientation;
  char facility_name[20];
  Int16 num_planes;
  Int16 num_frames;
  Int16 num_gates;
  Int16 num_bed_pos;
  float init_bed_position;
  float bed_position[15];
  float plane_separation;
  Int16 lwr_sctr_thres;
  Int16 lwr_true_thres;
  Int16 upr_true_thres;
  char user_process_code[10];
  Int16 acquisition_mode;
  float bin_size;
  float branching_fraction;
  Uint32 dose_start_time;
  float dosage;
  float well_counter_corr_factor;
  char data_units[32];
  Int16 septa_state;
  Int16 fill_cti[6];

} Mdc_Main_header7;

#define MH_72_SIZE       512

typedef struct mdc_mat_scan_subheader {
	Int16		data_type,
			dimension_1,
			dimension_2,
			smoothing,
			processing_code;
	float		sample_distance,
			isotope_halflife;
	Int16		frame_duration_sec;
	Int32		gate_duration,
			r_wave_offset;
	float		scale_factor;
	Int16		scan_min,
			scan_max;
	Int32		prompts,
			delayed,
			multiples,
			net_trues;
	float		cor_singles[16],
			uncor_singles[16],
			tot_avg_cor,
			tot_avg_uncor;
	Int32		total_coin_rate,
			frame_start_time,
			frame_duration;
	float		loss_correction_fctr;
	Int32		phy_planes[8];

} Mdc_Scan_subheader;

#define SSH_64_SIZE 236

typedef struct mdc_mat_scan_subheader7 {

  Int16 data_type;
  Int16 num_dimensions;
  Int16 num_r_elements;
  Int16 num_angles;
  Int16 corrections_applied;
  Int16 num_z_elements;
  Int16 ring_difference;
  float x_resolution;
  float y_resolution;
  float z_resolution;
  float w_resolution;
  Int16 fill[6];
  Uint32 gate_duration;
  Int32 r_wave_offset;
  Int32 num_accepted_beats;
  float scale_factor;
  Int16 scan_min;
  Int16 scan_max;
  Int32 prompts;
  Int32 delayed;
  Int32 multiples;
  Int32 net_trues;
  float cor_singles[16];
  float uncor_singles[16];
  float tot_avg_cor;
  float tot_avg_uncor;
  Int32 total_coin_rate;
  Uint32 frame_start_time;
  Uint32 frame_duration;
  float deadtime_correction_factor;
  Int16 phy_planes[8];
  Int16 cti_fill[83];
  Int16 user_fill[50];

} Mdc_Scan_subheader7;

#define SSH_72_SIZE   234

typedef struct mdc_mat_image_subheader {
	Int16		data_type,
			num_dimensions,
			dimension_1,
			dimension_2;
	float		x_origin,
			y_origin,
			recon_scale,	/* Image ZOOM from reconstruction */
			quant_scale;	/* Scale Factor */
	Int16		image_min,
			image_max;
	float		pixel_size,
			slice_width;
	Int32		frame_duration,
			frame_start_time;
	Int16		slice_location,
			recon_start_hour,
			recon_start_minute,
			recon_start_sec;
	Int32		gate_duration;
	Int16		filter_code;
	Int32		scan_matrix_num,
			norm_matrix_num,
			atten_cor_matrix_num;
	float		image_rotation,
			plane_eff_corr_fctr,
			decay_corr_fctr,
			loss_corr_fctr,
			intrinsic_tilt ;
	Int16		processing_code,
			quant_units,
			recon_start_day,
			recon_start_month,
			recon_start_year;
	float		ecat_calibration_fctr,
			well_counter_cal_fctr,
			filter_params[6];
	char		annotation[40];

} Mdc_Image_subheader;

#define ISH_64_SIZE 172

typedef struct mdc_mat_image_subheader7 {

  Int16 data_type;
  Int16 num_dimensions;
  Int16 x_dimension;
  Int16 y_dimension;
  Int16 z_dimension;
  float x_offset;
  float y_offset;
  float z_offset;
  float recon_zoom;
  float scale_factor;
  Int16 image_min;
  Int16 image_max;
  float x_pixel_size;
  float y_pixel_size;
  float z_pixel_size;
  Uint32 frame_duration;
  Uint32 frame_start_time;
  Int16 filter_code;
  float x_resolution;
  float y_resolution;
  float z_resolution;
  float num_r_elements;
  float num_angles;
  float z_rotation_angle;
  float decay_corr_fctr;
  Int32 processing_code;
  Uint32 gate_duration;
  Int32 r_wave_offset;
  Int32 num_accepted_beats;
  float filter_cutoff_frequency;
  float filter_resolution;
  float filter_ramp_slope;
  Int16 filter_order;
  float filter_scatter_fraction;
  float filter_scatter_slope;
  char annotation[40];
  float mt_1_1;
  float mt_1_2;
  float mt_1_3;
  float mt_2_1;
  float mt_2_2;
  float mt_2_3;
  float mt_3_1;
  float mt_3_2;
  float mt_3_3;
  float rfilter_cutoff;
  float rfilter_resolution;
  Int16 rfilter_code;
  Int16 rfilter_order;
  float zfilter_cutoff;
  float zfilter_resolution;
  Int16 zfilter_code;
  Int16 zfilter_order;
  float mt_1_4;
  float mt_2_4;
  float mt_3_4;
  Int16 scatter_type;
  Int16 recon_type;
  Int16 recon_views;
  Int16 fill_cti[87];
  Int16 fill_user[48];

} Mdc_Image_subheader7;

#define ISH_72_SIZE  510

typedef struct mdc_mat_norm_subheader {
	Int16		data_type,
			dimension_1,
			dimension_2;
	float		scale_factor;
	Int16		norm_hour,
			norm_minute,
			norm_second,
			norm_day,
			norm_month,
			norm_year;
	float		fov_source_width;
	float		ecat_calib_factor;

} Mdc_Norm_subheader; 

#define NSH_64_SIZE 30

typedef struct mdc_mat_norm_subheader7 {

  Int16 data_type;
  Int16 num_dimensions;
  Int16 num_r_elements;
  Int16 num_angles;
  Int16 num_z_elements;
  Int16 ring_difference;
  float scale_factor;
  float norm_min;
  float norm_max;
  float fov_source_width;
  float norm_quality_factor;
  Int16 norm_quality_factor_code;
  Int16 storage_order;
  Int16 span;
  Int16 z_elements[64];
  Int16 cti_fill[123];
  Int16 user_fill[50];

} Mdc_Norm_subheader7;

#define NSH_72_SIZE   166

typedef struct mdc_mat_attn_subheader {
	Int16		data_type,
			attenuation_type,
			dimension_1,
			dimension_2;
	float		scale_factor,
			x_origin,
			y_origin,
			x_radius,
			y_radius,
			tilt_angle,
			attenuation_coeff,
			sample_distance;

} Mdc_Attn_subheader;

#define ASH_64_SIZE 40

typedef struct mdc_mat_attn_subheader7 {

  Int16 data_type;
  Int16 num_dimensions;
  Int16 attenuation_type;
  Int16 num_r_elements;
  Int16 num_angles;
  Int16 num_z_elements;
  Int16 ring_difference;
  float x_resolution;
  float y_resolution;
  float z_resolution;
  float w_resolution;
  float scale_factor;
  float x_offset;
  float y_offset;
  float x_radius;
  float y_radius;
  float tilt_angle;
  float attenuation_coeff;
  float attenuation_min;
  float attenuation_max;
  float skull_thickness;
  Int16 num_xtra_atten_coeff;
  float xtra_atten_coeff[8];
  float edge_finding_threshold;
  Int16 storage_order;
  Int16 span;
  Int16 z_elements[64];
  Int16 fill_unused[86];
  Int16 fill_user[50];

} Mdc_Attn_subheader7;

#define ASH_72_SIZE   512

typedef struct mdc_matdirnode {
        Int32 matnum;
        Int32 strtblk;
        Int32 endblk;
        Int32 matstat;
        struct mdc_matdirnode *next;
} Mdc_MatDirNode;

typedef struct mdc_matdirlist {
        Int32 nmats;
        Mdc_MatDirNode *first;
        Mdc_MatDirNode *last;
} Mdc_MatDirList;

typedef struct mdc_matrixdata {
        Int32 mat_type;
        Int32 matnum;
        Uint8 *shptr;
        Uint8 *data_ptr;
        Int32 nviews;
        Int32 nelements;
        Int32 nblks;
        Int32 data_type;
} Mdc_MatrixData;

typedef struct mdc_matrix_file {
        Mdc_Main_header *mhptr;
        Mdc_MatDirList  *dirlist;
        FILE        *fptr;
        Int32       mode;
        char        *fname[80];
} Mdc_MatrixFile;

typedef struct mdc_matdirblk {
        Int32 nfree, nextblk, prvblk, nused;
        struct Mdc_MatDir matdir[31];
} Mdc_MatDirBlk;

#define BYTE_TYPE       1
#define VAX_I2          2
#define VAX_I4          3
#define VAX_R4          4
#define IEEE_R4         5
#define M68K_I2         6
#define M68K_I4         7
#define SUN_I2  M68K_I2
#define SUN_I4  M68K_I4
#define SUN_R4  IEEE_R4

#define RAW_DATA        1
#define IMAGE_DATA      2
#define ATTN_DATA       3
#define NORM_DATA       4
#define SUN_READ        1
#define SUN_WRITE       2
#define ACS_READ        3
#define ACS_WRITE       4
#define SUN_CREATE      5

#define ACQM_NORMAL      0  /* normal acquisition mode */
#define ACQM_RODTRN      1  /* rod transmission mode */
#define ACQM_RODTRN_KEEP 2  /* rod transmission mode keep all sinograms */
#define ACQM_DWIN_KEEP   3  /* dual window mode keep all sinograms */
#define ACQM_DWIN        4  /* dual window mode */
#define ACQM_SIMULT      5  /* simultaneous transmission/ emission mode */

/* eNlf: BEGIN - unnecessary, avoid conflicts! */
/* #define ERROR   -1                          */
/* #define OK 0                                */
/* eNlf: END   - unnecessary, avoid conflicts! */

/****************************************************************************
                            F U N C T I O N S
****************************************************************************/
Int32 MdcSWAW( Uint16 from[], Uint16 to[], Int32 length);
Int32 MdcSWAB( Uint8  from[], Uint8  to[], Int32 length);
FILE *mdc_mat_open(char *fname, char *fmode);
void mdc_mat_close(FILE *fptr);
Int32 mdc_mat_rblk(FILE *fptr, Int32 blkno, Uint8 *bufr, Int32 nblks);
Int32 mdc_mat_list(FILE *fptr, struct Mdc_MatDir mlist[], Int32 lmax);
Int32 mdc_mat_list7(FILE *fptr, struct Mdc_MatDir mlist[], Int32 lmax);
Int32 mdc_mat_numcod(Int32 frame, Int32 plane, Int32 gate, Int32 data, Int32 bed);
Int32 mdc_mat_numdoc( Int32 mdc_matnum, struct Mdc_Matval *matval);
Int32 mdc_mat_lookup(FILE *fptr, Int32 matnum, struct Mdc_MatDir *entry);
Int32 mdc_mat_lookup7(FILE *fptr, Int32 matnum, struct Mdc_MatDir *entry);
Int32 mdc_mat_read_main_header(FILE *fptr, Mdc_Main_header *h);
Int32 mdc_mat_read_main_header7(FILE *fptr, Mdc_Main_header7 *h);
Int32 mdc_mat_read_matrix_data(FILE *fptr, Int32 blk, Int32 nblks, Int16 bufr[]);
Int32 mdc_mat_read_mat_data(FILE *fptr, Int32 strtblk, Int32 nblks, Uint8 *dptr, Int32 dtype);
Int32 mdc_mat_read_mat_data7(FILE *fptr, Int32 strtblk, Int32 nblks, Uint8 *dptr, Int32 dtype);
Int32 mdc_mat_read_scan_subheader(FILE *fptr, Int32 blknum, Mdc_Scan_subheader *h);
Int32 mdc_mat_read_scan_subheader7(FILE *fptr, Int32 blknum, Mdc_Scan_subheader7 *h);
Int32 mdc_mat_read_image_subheader(FILE *fptr, Int32 blknum, Mdc_Image_subheader *h);
Int32 mdc_mat_read_image_subheader7(FILE *fptr, Int32 blknum, Mdc_Image_subheader7 *h);
float mdc_get_vax_float(Uint16 bufr[], Int32 off);
Int32 mdc_get_vax_long(Uint16 bufr[], Int32 off);
Mdc_Mat_dir mdc_mat_read_dir(FILE *fptr, Uint8 *selector);
Int32 mdc_mat_wblk(FILE *fptr, Int32 blkno, Uint8 *bufr, Int32 nblks);
FILE *mdc_mat_create(char *fname, Mdc_Main_header *mhead);
Int32 mdc_mat_enter(FILE *fptr, Int32 matnum, Int32 nblks);
Int32 mdc_mat_write_image(FILE *fptr, Int32 matnum, Mdc_Image_subheader *header, Uint16 *data, Int32 data_size);
Int32 mdc_mat_write_scan(FILE *fptr, Int32 matnum, Mdc_Scan_subheader *header, Uint16 *data, Int32 data_size);
Int32 mdc_mat_write_attn(FILE *fptr, Int32 matnum, Mdc_Attn_subheader *header, float *data, Int32 data_size);
Int32 mdc_mat_write_norm(FILE *fptr, Int32 matnum, Mdc_Norm_subheader *header, float *data, Int32 data_size);
Int32 mdc_mat_write_idata(FILE *fptr, Int32 blk, Uint8 *data, Int32 size);
Int32 mdc_mat_write_fdata(FILE *fptr, Int32 blk, float *data, Int32 size);
Int32 mdc_matrix_selector(Int32 matnum, Int32 ranges[2][5]);
Int32 mdc_decode_selector(char *s1, Int32 ranges[2][5]);
Int32 mdc_str_find(char *s1, char *s2);
Int32 mdc_str_replace(char *s1, char *s2, char *s3, char *s4);
Int32 mdc_string_replace(char *s1, char *s2, char *s3, char *s4);
Int32 mdc_fix_selector(char *s1, char *s2);
char* mdc_nex_word(char *s, char *w);
Int32 mdc_hostftovaxf(float f_orig, Uint16 number[]);
Int32 mdc_mat_write_main_header(FILE *fptr, Mdc_Main_header *header);
Int32 mdc_mat_write_image_subheader(FILE *fptr, Int32 blknum, Mdc_Image_subheader *header);
Int32 mdc_hostltovaxl(Int32 in, Uint16 out[2]);
Int32 mdc_mat_write_scan_subheader(FILE *fptr, Int32 blknum, Mdc_Scan_subheader *header);
Int32 mdc_mat_write_attn_subheader(FILE *fptr, Int32 blknum, Mdc_Attn_subheader *header);
Int32 mdc_mat_write_norm_subheader(FILE *fptr, Int32 blknum, Mdc_Norm_subheader *header);
Int32 mdc_mat_read_attn_subheader(FILE *fptr, Int32 blknum, Mdc_Attn_subheader *header);
Int32 mdc_mat_read_attn_subheader7(FILE *fptr, Int32 blknum, Mdc_Attn_subheader7 *h);
Int32 mdc_mat_read_norm_subheader(FILE *fptr, Int32 blknum, Mdc_Norm_subheader *header);
Int32 mdc_mat_read_norm_subheader7(FILE *fptr, Int32 blknum, Mdc_Norm_subheader7 *header);
Int32 mdc_write_matrix_data(FILE *fptr, Int32 strtblk, Int32 nblks, Uint8 *dptr, Int32 dtype);
double  mdc_mat_qs(double *X, double *Z, Int32 lod);
double  mdc_mat_max(double *X, Int32 lod);
double  mdc_mat_min(double *X, Int32 lod);
Int32 mdc_mat_get_spec (char *file, Int32 *num_frames, Int32 *num_planes, Int32 *num_gates, Int32 *num_bed);
void mdc_anatomical_sort (struct Mdc_MatDir matrix_list[], Int32 num_matrices, Mdc_Main_header *mhead, Int32 num_bed_pos);
void mdc_matnum_sort(struct Mdc_MatDir mlist[], Int32 num_entry);
void mdc_plane_sort (struct Mdc_MatDir matrix_list[], Int32 num_matrices);

#endif

