/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * 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  *
 *                                                                         *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
 */

/*
   Copyright (C) 1997-2021 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];
  Int32 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;
  Int32 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

