/*  \brief  ReconstructedVolume class */

class Reconstruct3D;
class NumericTextFile;

class ReconstructedVolume {

public:

	float						pixel_size;
	float						mask_volume_in_voxels;
	float						molecular_mass_in_kDa;
	float						mask_radius;
	wxString 					symmetry_symbol;
	SymmetryMatrix				symmetry_matrices;
	Image						density_map;
	Image						current_projection;
//	ResolutionStatistics		statistics;
	float						current_resolution_limit;
	float						current_ctf;
	float						current_phi;
	float						current_theta;
	float						current_psi;
	float						current_shift_x;
	float						current_shift_y;
	float						current_mask_radius;
	float						current_mask_falloff;
	bool						current_whitening;
	bool						current_swap_quadrants;

	bool						has_been_initialized;
	bool						has_masked_applied;
	bool						was_corrected;
//	bool						has_statistics;
	bool						has_been_filtered;
	bool						whitened_projection;

	ReconstructedVolume(float wanted_molecular_mass_in_kDa = 0.0);
	~ReconstructedVolume();

	ReconstructedVolume & operator = (const ReconstructedVolume &t);
	ReconstructedVolume & operator = (const ReconstructedVolume *t);

	void Deallocate();
	void InitWithReconstruct3D(Reconstruct3D &image_reconstruction, float wanted_pixel_size);
	void InitWithDimensions(int wanted_logical_x_dimension, int wanted_logical_y_dimension, int wanted_logical_z_dimension, float wanted_pixel_size, wxString = "C1");
	void PrepareForProjections(float low_resolution_limit, float high_resolution_limit, bool approximate_binning = false, bool apply_binning = true);
//	void PrepareForProjections(float resolution_limit, bool approximate_binning = false, bool apply_binning = true);
	void CalculateProjection(Image &projection, Image &CTF, AnglesAndShifts &angles_and_shifts_of_projection, float mask_radius = 0.0, float mask_falloff = 0.0,
			float resolution_limit = 1.0, bool swap_quadrants = false, bool apply_shifts = false, bool whiten = false, bool apply_ctf = false, bool abolute_ctf = false);
	void Calculate3DSimple(Reconstruct3D &reconstruction);
	void Calculate3DOptimal(Reconstruct3D &reconstruction, ResolutionStatistics &statistics, float weiner_filter_nominater = 1.0f);
	float Correct3D(float mask_radius = 0.0);
	void CosineRingMask(float wanted_inner_mask_radius, float wanted_outer_mask_radius, float wanted_mask_edge);
	void CosineMask(float wanted_mask_radius, float wanted_mask_edge);
	void OptimalFilter(ResolutionStatistics &statistics);
	void FinalizeSimple(Reconstruct3D &reconstruction, int &original_box_size, float &original_pixel_size, float &pixel_size,
			float &inner_mask_radius, float &outer_mask_radius, float &mask_falloff, wxString &output_volume);
	void FinalizeOptimal(Reconstruct3D &reconstruction, Image &density_map_1, Image &density_map_2,
			float &original_pixel_size, float &pixel_size, float &inner_mask_radius, float &outer_mask_radius, float &mask_falloff,
			bool center_mass, wxString &output_volume, NumericTextFile &output_statistics, ResolutionStatistics *copy_of_statistics = NULL, float weiner_filter_nominator = 1.0f);
	void FinalizeML(Reconstruct3D &reconstruction, Image &density_map_1, Image &density_map_2,
			float &original_pixel_size, float &pixel_size, float &inner_mask_radius, float &outer_mask_radius, float &mask_falloff,
			wxString &output_volume, NumericTextFile &output_statistics, ResolutionStatistics *copy_of_statistics = NULL);
	void Calculate3DML(Reconstruct3D &reconstruction);
	float ComputeOrientationDistributionEfficiency(Reconstruct3D &reconstruction);
};
