/*  \brief  Reconstruct3D class (derived from Frealign Pinsert) */

class Particle;

class Reconstruct3D {

public:

	float						pixel_size;
	float						original_pixel_size;
	float						average_occupancy;
	float						average_score;
	float						score_weights_conversion;
	SymmetryMatrix				symmetry_matrices;
	bool						edge_terms_were_added;
	bool						center_mass;
	int							correct_ewald_sphere;

	Image						image_reconstruction;
	float						*ctf_reconstruction;

	int 						logical_x_dimension;		// !< Logical (X) dimensions of the image., Note that this does not necessarily correspond to memory allocation dimensions (ie physical dimensions).
	int 						logical_y_dimension;		// !< Logical (Y) dimensions of the image., Note that this does not necessarily correspond to memory allocation dimensions (ie physical dimensions).
	int 						logical_z_dimension;		// !< Logical (Z) dimensions of the image., Note that this does not necessarily correspond to memory allocation dimensions (ie physical dimensions).
	int 						original_x_dimension;
	int 						original_y_dimension;
	int 						original_z_dimension;

	int							images_processed;

	Reconstruct3D(float wanted_pixel_size = 0.0, float wanted_average_occupancy = 0.0, float wanted_average_score = 0.0, float wanted_score_weights_conversion = 0.0, int wanted_correct_ewald_sphere = 0);
	Reconstruct3D(float wanted_pixel_size, float wanted_average_occupancy, float wanted_average_score, float wanted_score_weights_conversion, wxString wanted_symmetry, int wanted_correct_ewald_sphere = 0);
	Reconstruct3D(int wanted_logical_x_dimension, int wanted_logical_y_dimension, int wanted_logical_z_dimension, float wanted_pixel_size, float wanted_average_occupancy, float wanted_average_score, float wanted_score_weights_conversion, wxString wanted_symmetry, int wanted_correct_ewald_sphere = 0);	// constructor with size
	~Reconstruct3D();							// destructor

	void FreeMemory();
	void Init(int wanted_logical_x_dimension, int wanted_logical_y_dimension, int wanted_logical_z_dimension, float wanted_pixel_size, float wanted_average_occupancy, float wanted_average_score, float wanted_score_weights_conversion, int wanted_correct_ewald_sphere = 0);
	void InsertSliceWithCTF(Particle &particle_to_insert, float symmetry_weight = 1.0);
	void InsertSliceNoCTF(Particle &particle_to_insert, float symmetry_weight = 1.0);
	void AddByLinearInterpolation(float &wanted_x_coordinate, float &wanted_y_coordinate, float &wanted_z_coordinate, std::complex<float> &wanted_value, std::complex<float> &ctf_value, float wanted_weight, bool complex_ctf = false);
	void CompleteEdges();
	float Correct3DCTF(Image &buffer3d);
	void DumpArrays(wxString filename, bool insert_even);
	void ReadArrayHeader(wxString filename, int &logical_x_dimension, int &logical_y_dimension, int &logical_z_dimension,
			int &original_x_dimension, int &original_y_dimension, int &original_z_dimension, int &images_processed, float &pixel_size, float &original_pixel_size,
			float &average_occupancy, float &average_score, float &score_weights_conversion, wxString &symmetry_symbol, bool &insert_even, bool &center_mass);
	void ReadArrays(wxString filename);
	Reconstruct3D operator + (const Reconstruct3D &other);
	Reconstruct3D &operator = (const Reconstruct3D &other);
	Reconstruct3D &operator = (const Reconstruct3D *other);
	Reconstruct3D &operator += (const Reconstruct3D &other);
	Reconstruct3D &operator += (const Reconstruct3D *other);
};
