コード例 #1
0
ファイル: make_parse_light.c プロジェクト: komamitsu/misc
static int calc(coins *saving, int price, coins *payment)
{
  int total;
  int i500, i100, i50, i10;
  coins payment_work, saving_work, record = 
    { MAX_COIN, MAX_COIN, MAX_COIN, MAX_COIN };

  for (i500 = 0; i500 <= saving->y500; i500++) {
    for (i100 = 0; i100 <= saving->y100; i100++) {
      for (i50 = 0; i50 <= saving->y50; i50++) {
        for (i10 = 0; i10 <= saving->y10; i10++) {
          payment_work.y500 = i500;
          payment_work.y100 = i100;
          payment_work.y50 = i50;
          payment_work.y10 = i10;
          saving_work = *saving;
          if (!pay(price, &saving_work, &payment_work)) {
            if (total_weight(&record) > 
                total_weight(&saving_work)) {
              *payment = payment_work;
              record = saving_work;
            }
          }
        }
      }
    }
  }

  return 0;
}
コード例 #2
0
MobileDive::MobileDive(dive *d)
{
	m_thisDive = d;
	setDiveNumber(QString::number(d->number));
	setDiveId(QString::number(d->id));

	dive_trip *trip = d->divetrip;

	if(trip) {
		//trip is valid
		setTrip(trip->location);
	}

	setDate(get_dive_date_string(d->when));
	setDepth(get_depth_string(d->maxdepth));
	setDuration(get_dive_duration_string(d->duration.seconds, "h:","min"));

	setupDiveTempDetails();

	weight_t tw = { total_weight(d) };
	setWeight(weight_string(tw.grams));

	setSuit(QString(d->suit));
	setCylinder(QString(d->cylinder[0].type.description));
	setSac(QString::number(d->sac));
	setLocation(get_dive_location(d));
	setNotes(d->notes);
	setBuddy(d->buddy);
	setDivemaster(d->divemaster);
}
コード例 #3
0
ファイル: models.cpp プロジェクト: Etiene/subsurface
QVariant DiveItem::data(int column, int role) const
{
	QVariant retVal;

	switch (role) {
	case Qt::TextAlignmentRole:
		switch (column) {
		case DATE: /* fall through */
		case SUIT: /* fall through */
		case LOCATION:
			retVal = Qt::AlignLeft;
			break;
		default:
			retVal = Qt::AlignRight;
			break;
		}
		break;
		case DiveTripModel::SORT_ROLE:
		switch (column) {
		case NR:		retVal = (qulonglong) dive->when; break;
		case DATE:		retVal = (qulonglong) dive->when; break;
		case RATING:		retVal = dive->rating; break;
		case DEPTH:		retVal = dive->maxdepth.mm; break;
		case DURATION:		retVal = dive->duration.seconds; break;
		case TEMPERATURE:	retVal = dive->watertemp.mkelvin; break;
		case TOTALWEIGHT:	retVal = total_weight(dive); break;
		case SUIT:		retVal = QString(dive->suit); break;
		case CYLINDER:		retVal = QString(dive->cylinder[0].type.description); break;
		case NITROX:		retVal = nitrox_sort_value(dive); break;
		case SAC:		retVal = dive->sac; break;
		case OTU:		retVal = dive->otu; break;
		case MAXCNS:		retVal = dive->maxcns; break;
		case LOCATION:		retVal = QString(dive->location); break;
		}
		break;
	case Qt::DisplayRole:
		switch (column) {
		case NR:		retVal = dive->number; break;
		case DATE:		retVal = displayDate(); break;
		case DEPTH:		retVal = displayDepth(); break;
		case DURATION:		retVal = displayDuration(); break;
		case TEMPERATURE:	retVal = displayTemperature(); break;
		case TOTALWEIGHT:	retVal = displayWeight(); break;
		case SUIT:		retVal = QString(dive->suit); break;
		case CYLINDER:		retVal = QString(dive->cylinder[0].type.description); break;
		case NITROX:		retVal = QString(get_nitrox_string(dive)); break;
		case SAC:		retVal = displaySac(); break;
		case OTU:		retVal = dive->otu; break;
		case MAXCNS:		retVal = dive->maxcns; break;
		case LOCATION:		retVal = QString(dive->location); break;
		}
		break;
	}

	if (role == DiveTripModel::STAR_ROLE)
		retVal = dive->rating;

	if (role == DiveTripModel::DIVE_ROLE)
		retVal = QVariant::fromValue<void*>(dive);

	if(role == DiveTripModel::DIVE_IDX){
		retVal = get_divenr(dive);
	}
	return retVal;
}
コード例 #4
0
ファイル: models.cpp プロジェクト: Etiene/subsurface
QVariant ProfilePrintModel::data(const QModelIndex &index, int role) const
{
	const int row = index.row();
	const int col = index.column();

	switch (role) {
	case Qt::DisplayRole: {
		struct DiveItem di;
		di.dive = dive;
		char buf[80];

		const QString unknown = tr("unknown");

		// dive# + date, depth, location, duration
		if (row == 0) {
			if (col == 0)
				return tr("Dive #%1 - %2").arg(dive->number).arg(di.displayDate());
			if (col == 5) {
				QString unit = (get_units()->length == units::METERS) ? "m" : "ft";
				return tr("Max depth: %1 %2").arg(di.displayDepth()).arg(unit);
			}
		}
		if (row == 1) {
			if (col == 0)
				return truncateString(dive->location, 32);
			if (col == 5)
				return QString(tr("Duration: %1 min")).arg(di.displayDuration());
		}
		// cylinder headings
		if (row == 2) {
			if (col == 0)
				return tr("Cylinder");
			if (col == 1)
				return tr("Gasmix");
			if (col == 2)
				return tr("Gas Used");
		}
		// cylinder data
		if (row > 2 && row < 10 && row - 3 < MAX_CYLINDERS) {
			cylinder_t *cyl = &dive->cylinder[row - 3];
			if (cyl->type.description) { // how do we check if a cylinder is added?
				if (col == 0) {
					if (cyl->type.description[0] != '\0')
						return QString(cyl->type.description);
					return unknown;
				}
				if (col == 1) {
					get_gas_string(cyl->gasmix.o2.permille, cyl->gasmix.he.permille, buf, sizeof(buf));
					return QString(buf);
				}
				if (col == 2) {
					return get_cylinder_used_gas_string(cyl, true);
				}
			}
		}
		// dive notes
		if (row == 10 && col == 0)
			return truncateString(dive->notes, 640);
		// sac, cns, otu - headings
		if (col == 3) {
			if (row == 2)
				return tr("SAC");
			if (row == 4)
				return tr("Max. CNS");
			if (row == 6)
				return tr("OTU");
		}
		// sac, cns, otu - data
		if (col == 4) {
			if (row == 2)
				return di.displaySac();
			if (row == 4)
				return QString::number(dive->maxcns);
			if (row == 6)
				return QString::number(dive->otu);
		}
		// weights heading
		if (row == 2 && col == 5)
			return tr("Weights");
		// total weight
		if (row == 9) {
			weight_t tw = { total_weight(dive) };
			if (tw.grams) {
				if (col == 5)
					return tr("Total weight");
				if (col == 6)
					return get_weight_string(tw, true);
			}
		}
		// weight data
		if (row > 2 && row < 10 && row - 3 < MAX_WEIGHTSYSTEMS) {
			weightsystem_t *ws = &dive->weightsystem[row - 3];
			if (ws->weight.grams) {
				if (col == 5) {
					if (ws->description && ws->description[0] != '\0')
						return QString(ws->description);
					return unknown;
				}
				if (col == 6) {
					return get_weight_string(ws->weight, true);
				}
			}
		}
		return QString();
	}
	case Qt::FontRole: {
		QFont font;
		const int baseSize = 9;
		// dive #
		if (row == 0 && col == 0) {
			font.setBold(true);
			font.setPixelSize(baseSize + 1);
			return QVariant::fromValue(font);
		}
		// dive location
		if (row == 1 && col == 0) {
			font.setPixelSize(baseSize);
			font.setBold(true);
			return QVariant::fromValue(font);
		}
		// depth/duration
		if ((row == 0 || row == 1) && col == 5) {
			font.setPixelSize(baseSize);
			return QVariant::fromValue(font);
		}
		// notes
		if (row == 9 && col == 0) {
			font.setPixelSize(baseSize + 1);
			return QVariant::fromValue(font);
		}
		font.setPixelSize(baseSize);
		return QVariant::fromValue(font);
	}
	case Qt::TextAlignmentRole: {
		unsigned int align = Qt::AlignCenter;
		// dive #, location, notes
		if ((row < 2 || row == 10) && col == 0)
			align = Qt::AlignLeft | Qt::AlignVCenter;
		// depth, duration
		if (row < 2 && col == 5)
			align = Qt::AlignRight | Qt::AlignVCenter;
		return QVariant::fromValue(align);
	}
	} // switch (role)
	return QVariant();
}
コード例 #5
0
ファイル: models.cpp プロジェクト: Etiene/subsurface
int DiveItem::weight() const
{
	weight_t tw = { total_weight(dive) };
	return tw.grams;
}
コード例 #6
0
ファイル: rops_estimation.hpp プロジェクト: 2php/pcl
template <typename PointInT, typename PointOutT> void
pcl::ROPSEstimation <PointInT, PointOutT>::computeLRF (const PointInT& point, const std::set <unsigned int>& local_triangles, Eigen::Matrix3f& lrf_matrix) const
{
  const unsigned int number_of_triangles = static_cast <unsigned int> (local_triangles.size ());

  std::vector<Eigen::Matrix3f, Eigen::aligned_allocator<Eigen::Matrix3f> > scatter_matrices (number_of_triangles);
  std::vector <float> triangle_area (number_of_triangles);
  std::vector <float> distance_weight (number_of_triangles);

  float total_area = 0.0f;
  const float coeff = 1.0f / 12.0f;
  const float coeff_1_div_3 = 1.0f / 3.0f;

  Eigen::Vector3f feature_point (point.x, point.y, point.z);

  std::set <unsigned int>::const_iterator it;
  unsigned int i_triangle = 0;
  for (it = local_triangles.begin (), i_triangle = 0; it != local_triangles.end (); it++, i_triangle++)
  {
    Eigen::Vector3f pt[3];
    for (unsigned int i_vertex = 0; i_vertex < 3; i_vertex++)
    {
      const unsigned int index = triangles_[*it].vertices[i_vertex];
      pt[i_vertex] (0) = surface_->points[index].x;
      pt[i_vertex] (1) = surface_->points[index].y;
      pt[i_vertex] (2) = surface_->points[index].z;
    }

    const float curr_area = ((pt[1] - pt[0]).cross (pt[2] - pt[0])).norm ();
    triangle_area[i_triangle] = curr_area;
    total_area += curr_area;

    distance_weight[i_triangle] = pow (support_radius_ - (feature_point - (pt[0] + pt[1] + pt[2]) * coeff_1_div_3).norm (), 2.0f);

    Eigen::Matrix3f curr_scatter_matrix;
    curr_scatter_matrix.setZero ();
    for (unsigned int i_pt = 0; i_pt < 3; i_pt++)
    {
      Eigen::Vector3f vec = pt[i_pt] - feature_point;
      curr_scatter_matrix += vec * (vec.transpose ());
      for (unsigned int j_pt = 0; j_pt < 3; j_pt++)
        curr_scatter_matrix += vec * ((pt[j_pt] - feature_point).transpose ());
    }
    scatter_matrices[i_triangle] = coeff * curr_scatter_matrix;
  }

  if (std::abs (total_area) < std::numeric_limits <float>::epsilon ())
    total_area = 1.0f / total_area;
  else
    total_area = 1.0f;

  Eigen::Matrix3f overall_scatter_matrix;
  overall_scatter_matrix.setZero ();
  std::vector<float> total_weight (number_of_triangles);
  const float denominator = 1.0f / 6.0f;
  for (unsigned int i_triangle = 0; i_triangle < number_of_triangles; i_triangle++)
  {
    float factor = distance_weight[i_triangle] * triangle_area[i_triangle] * total_area;
    overall_scatter_matrix += factor * scatter_matrices[i_triangle];
    total_weight[i_triangle] = factor * denominator;
  }

  Eigen::Vector3f v1, v2, v3;
  computeEigenVectors (overall_scatter_matrix, v1, v2, v3);

  float h1 = 0.0f;
  float h3 = 0.0f;
  for (it = local_triangles.begin (), i_triangle = 0; it != local_triangles.end (); it++, i_triangle++)
  {
    Eigen::Vector3f pt[3];
    for (unsigned int i_vertex = 0; i_vertex < 3; i_vertex++)
    {
      const unsigned int index = triangles_[*it].vertices[i_vertex];
      pt[i_vertex] (0) = surface_->points[index].x;
      pt[i_vertex] (1) = surface_->points[index].y;
      pt[i_vertex] (2) = surface_->points[index].z;
    }

    float factor1 = 0.0f;
    float factor3 = 0.0f;
    for (unsigned int i_pt = 0; i_pt < 3; i_pt++)
    {
      Eigen::Vector3f vec = pt[i_pt] - feature_point;
      factor1 += vec.dot (v1);
      factor3 += vec.dot (v3);
    }
    h1 += total_weight[i_triangle] * factor1;
    h3 += total_weight[i_triangle] * factor3;
  }

  if (h1 < 0.0f) v1 = -v1;
  if (h3 < 0.0f) v3 = -v3;

  v2 = v3.cross (v1);

  lrf_matrix.row (0) = v1;
  lrf_matrix.row (1) = v2;
  lrf_matrix.row (2) = v3;
}
コード例 #7
0
QVariant DiveItem::data(int column, int role) const
{
	QVariant retVal;
	struct dive *dive = get_dive_by_uniq_id(diveId);
	if (!dive)
		return QVariant();

	switch (role) {
	case Qt::TextAlignmentRole:
		retVal = dive_table_alignment(column);
		break;
	case DiveTripModel::SORT_ROLE:
		Q_ASSERT(dive != NULL);
		switch (column) {
		case NR:
			retVal = (qulonglong)dive->when;
			break;
		case DATE:
			retVal = (qulonglong)dive->when;
			break;
		case RATING:
			retVal = dive->rating;
			break;
		case DEPTH:
			retVal = dive->maxdepth.mm;
			break;
		case DURATION:
			retVal = dive->duration.seconds;
			break;
		case TEMPERATURE:
			retVal = dive->watertemp.mkelvin;
			break;
		case TOTALWEIGHT:
			retVal = total_weight(dive);
			break;
		case SUIT:
			retVal = QString(dive->suit);
			break;
		case CYLINDER:
			retVal = QString(dive->cylinder[0].type.description);
			break;
		case GAS:
			retVal = nitrox_sort_value(dive);
			break;
		case SAC:
			retVal = dive->sac;
			break;
		case OTU:
			retVal = dive->otu;
			break;
		case MAXCNS:
			retVal = dive->maxcns;
			break;
		case LOCATION:
			retVal = QString(get_dive_location(dive));
			break;
		}
		break;
	case Qt::DisplayRole:
		Q_ASSERT(dive != NULL);
		switch (column) {
		case NR:
			retVal = dive->number;
			break;
		case DATE:
			retVal = displayDate();
			break;
		case DEPTH:
			retVal = displayDepth();
			break;
		case DURATION:
			retVal = displayDuration();
			break;
		case TEMPERATURE:
			retVal = displayTemperature();
			break;
		case TOTALWEIGHT:
			retVal = displayWeight();
			break;
		case SUIT:
			retVal = QString(dive->suit);
			break;
		case CYLINDER:
			retVal = QString(dive->cylinder[0].type.description);
			break;
		case SAC:
			retVal = displaySac();
			break;
		case OTU:
			retVal = dive->otu;
			break;
		case MAXCNS:
			retVal = dive->maxcns;
			break;
		case LOCATION:
			retVal = QString(get_dive_location(dive));
			break;
		case GAS:
			const char *gas_string = get_dive_gas_string(dive);
			retVal = QString(gas_string);
			free((void*)gas_string);
			break;
		}
		break;
	case Qt::DecorationRole:
		if (column == LOCATION)
			if (dive_has_gps_location(dive)) {
				IconMetrics im = defaultIconMetrics();
				retVal = QIcon(":satellite").pixmap(im.sz_small, im.sz_small);
			}
		break;
	case Qt::ToolTipRole:
		switch (column) {
		case NR:
			retVal = tr("#");
			break;
		case DATE:
			retVal = tr("Date");
			break;
		case RATING:
			retVal = tr("Rating");
			break;
		case DEPTH:
			retVal = tr("Depth(%1)").arg((get_units()->length == units::METERS) ? tr("m") : tr("ft"));
			break;
		case DURATION:
			retVal = tr("Duration");
			break;
		case TEMPERATURE:
			retVal = tr("Temp(%1%2)").arg(UTF8_DEGREE).arg((get_units()->temperature == units::CELSIUS) ? "C" : "F");
			break;
		case TOTALWEIGHT:
			retVal = tr("Weight(%1)").arg((get_units()->weight == units::KG) ? tr("kg") : tr("lbs"));
			break;
		case SUIT:
			retVal = tr("Suit");
			break;
		case CYLINDER:
			retVal = tr("Cyl");
			break;
		case GAS:
			retVal = tr("Gas");
			break;
		case SAC:
			const char *unit;
			get_volume_units(0, NULL, &unit);
			retVal = tr("SAC(%1)").arg(QString(unit).append(tr("/min")));
			break;
		case OTU:
			retVal = tr("OTU");
			break;
		case MAXCNS:
			retVal = tr("Max CNS");
			break;
		case LOCATION:
			retVal = tr("Location");
			break;
		}
		break;
	}

	if (role == DiveTripModel::STAR_ROLE) {
		Q_ASSERT(dive != NULL);
		retVal = dive->rating;
	}
	if (role == DiveTripModel::DIVE_ROLE) {
		retVal = QVariant::fromValue<void *>(dive);
	}
	if (role == DiveTripModel::DIVE_IDX) {
		Q_ASSERT(dive != NULL);
		retVal = get_divenr(dive);
	}
	return retVal;
}
コード例 #8
0
int DiveItem::weight() const
{
	struct dive *dive = get_dive_by_uniq_id(diveId);
	weight_t tw = { total_weight(dive) };
	return tw.grams;
}
コード例 #9
0
ファイル: models.cpp プロジェクト: ryanlerch/subsurface
QVariant ProfilePrintModel::data(const QModelIndex &index, int role) const
{
	const int row = index.row();
	const int col = index.column();

	switch (role) {
	case Qt::DisplayRole: {
		struct dive *dive = get_dive_by_uniq_id(diveId);
		struct DiveItem di;
		di.diveId = diveId;

		const QString unknown = tr("unknown");

		// dive# + date, depth, location, duration
		if (row == 0) {
			if (col == 0)
				return tr("Dive #%1 - %2").arg(dive->number).arg(di.displayDate());
			if (col == 3) {
				QString unit = (get_units()->length == units::METERS) ? "m" : "ft";
				return tr("Max depth: %1 %2").arg(di.displayDepth()).arg(unit);
			}
		}
		if (row == 1) {
			if (col == 0)
				return QString(dive->location);
			if (col == 3)
				return QString(tr("Duration: %1 min")).arg(di.displayDuration());
		}
		// headings
		if (row == 2) {
			if (col == 0)
				return tr("Gas used:");
			if (col == 2)
				return tr("Tags:");
			if (col == 3)
				return tr("SAC:");
			if (col == 4)
				return tr("Weights:");
		}
		// notes
		if (col == 0) {
			if (row == 6)
				return tr("Notes:");
			if (row == 7)
				return QString(dive->notes);
		}
		// more headings
		if (row == 4) {
			if (col == 0)
				return tr("Divemaster:");
			if (col == 1)
				return tr("Buddy:");
			if (col == 2)
				return tr("Suit:");
			if (col == 3)
				return tr("Viz:");
			if (col == 4)
				return tr("Rating:");
		}
		// values for gas, sac, etc...
		if (row == 3) {
			if (col == 0) {
				int added = 0;
				QString gas, gases;
				for (int i = 0; i < MAX_CYLINDERS; i++) {
					if (!is_cylinder_used(dive, i))
						continue;
					gas = dive->cylinder[i].type.description;
					gas += QString(!gas.isEmpty() ? " " : "") + gasname(&dive->cylinder[i].gasmix);
					// if has a description and if such gas is not already present
					if (!gas.isEmpty() && gases.indexOf(gas) == -1) {
						if (added > 0)
							gases += QString(" / ");
						gases += gas;
						added++;
					}
				}
				return gases;
			}
			if (col == 2) {
				char buffer[256];
				taglist_get_tagstring(dive->tag_list, buffer, 256);
				return QString(buffer);
			}
			if (col == 3)
				return di.displaySac();
			if (col == 4) {
				weight_t tw = { total_weight(dive) };
				return get_weight_string(tw, true);
			}
		}
		// values for DM, buddy, suit, etc...
		if (row == 5) {
			if (col == 0)
				return QString(dive->divemaster);
			if (col == 1)
				return QString(dive->buddy);
			if (col == 2)
				return QString(dive->suit);
			if (col == 3)
				return (dive->visibility) ? QString::number(dive->visibility).append(" / 5") : QString();
			if (col == 4)
				return (dive->rating) ? QString::number(dive->rating).append(" / 5") : QString();
		}
		return QString();
	}
	case Qt::FontRole: {
		QFont font;
		font.setPointSizeF(fontSize);
		if (row == 0 && col == 0) {
			font.setBold(true);
		}
		return QVariant::fromValue(font);
	}
	case Qt::TextAlignmentRole: {
		// everything is aligned to the left
		unsigned int align = Qt::AlignLeft;
		// align depth and duration right
		if (row < 2 && col == 4)
			align = Qt::AlignRight | Qt::AlignVCenter;
		return QVariant::fromValue(align);
	}
	} // switch (role)
	return QVariant();
}
int main(int argc, char *argv[]){
    /**
     EXPLANATION:
     This function computes the average of the (projected) deltas as a function of redshift
     Note that this program should work with typical ini file developed to pass to correlation.run but that not all options are used here.
     This program should be run for each set of the paramenters z_min_interpolation, z_max_interpolation, num_points_interpolation, 
     or pixel_separation
          
     INPUTS:
     input_file[optional] - a file containing the input settings
     
     OUTPUTS:
     NONE
          
     CLASSES USED:
     AstroObjectDataset
     Input
     PlateNeighbours
     LyaSpectraDataset
     
     FUNCITONS USED:
     ComputePlateNeighbours
     */
    
    // load time control variables
    time_t start_time,end_time;
    time(&start_time);

    // load global variables and plot object
    std::cout << "Initializing variables" << std::endl;
    string input_filename = "";
    if (argc > 1){
        input_filename += argv[1];
    }
    Input input(input_filename);
    size_t flag_verbose_main = input.flag_verbose_main();
    const PlotsObject kPlots(input);

    // check whether or not this comuputation is necessary
    if (not input.flag_project_deltas()){
        std::cout << "Deltas are not projected, correction unnecessary" << std::endl;
        return 0;
    }
    
    // check whether or not the plate list needs to be computed
    if (input.flag_compute_plate_neighbours()){
        ComputePlateNeighbours(input);
    }
    // load plate list
    const PlateNeighbours kPlateNeighbours(input);
    
    // load spectra dataset
    std::auto_ptr<SpectraDataset> spectra_list;
    if (input.dataset2_type() == "lya"){
        spectra_list.reset(new LyaSpectraDataset(input));
    }
    else if (input.dataset2_type() == "civ"){
        spectra_list.reset(new CIVSpectraDataset(input));
    }
    else{
        std::cout << "Error : The selected type for dataset2 is not enabled. Current options are: " << input.dataset2_type_options() << std::endl;
        return 1;
    }
    if (input.flag_plot_catalog_info()){
        if (flag_verbose_main >= 2){
            std::cout << "Plotting spectra dataset information" << std::endl;
        }
        kPlots.PlotRADECDispersion(*spectra_list, true);
        kPlots.PlotZHistogram(*spectra_list, true);
        if (flag_verbose_main >= 2){
            std::cout << "done" << std::endl;
        }
    }
    
    // define vectors to store the average projected delta as a function of redshift
    size_t num_points_interpolation = input.num_points_interpolation();
    std::vector<double> z_mean_delta(num_points_interpolation, 0.0);
    double z_step = (input.z_max_interpolation() - input.z_min_interpolation())/float(z_mean_delta.size());
    for (size_t index = 0; index < z_mean_delta.size(); index++){
        z_mean_delta[index] = input.z_min_interpolation() + z_step*float(index);
    }
    std::vector<double> mean_delta(num_points_interpolation, 0.0);
    std::vector<double> total_weight(num_points_interpolation, 0.0);
    
    // define copies of mean_delta and total_weight for each of the threads
    int num_threads = atoi(std::getenv("OMP_NUM_THREADS"));
    std::vector<std::vector<double> > mean_delta_thread;
    mean_delta_thread.resize(num_threads, mean_delta);
    std::vector<std::vector<double> > total_weight_thread;
    total_weight_thread.resize(num_threads, total_weight);
    
    // load list of plates
    PlatesMapVector<LyaSpectrum>::map plates_list = (*spectra_list).list();
    
    // compute the average of projected deltas
    std::cout << "Computing the average of projected deltas" << std::endl;
    // loop over plates
    for (PlatesMapVector<LyaSpectrum>::map::iterator it = plates_list.begin(); it != plates_list.end(); it ++){
        
        std::vector<LyaSpectrum> spec_list = (*it).second;
        // loop over spectra
        #pragma omp parallel for schedule(dynamic)
        for (size_t spectrum_number = 0; spectrum_number < spec_list.size(); spectrum_number ++){
            // get the thread number
            int thread_num = omp_get_thread_num();
            double weight;
            
            std::vector<LyaPixel> spectrum = spec_list[spectrum_number].spectrum();
            // loop over pixel
            for (size_t pixel_number = 0; pixel_number < spectrum.size(); pixel_number++){
                // locate the bin in z the pixel belongs to
                int z_index = int((spectrum[pixel_number].z() - input.z_min_interpolation())/z_step);
                if ((z_index < 0) or (z_index > z_mean_delta.size())){
                    #pragma omp critical (cerr)
                    {
                        std::cerr << "Bad index, z_index = " << z_index << std::endl;
                    }
                }
                else{
                    weight = spectrum[pixel_number].weight();
                    mean_delta_thread[thread_num][z_index] += spectrum[pixel_number].delta()*weight;
                    total_weight_thread[thread_num][z_index] += weight;
                }
            }
        }
    }
    
    // combine the measurements from the different threads
    for (size_t index = 0; index < num_points_interpolation; index ++){
        for (size_t thread_num = 0; thread_num < mean_delta_thread.size(); thread_num ++){
            mean_delta[index] += mean_delta_thread[thread_num][index];
            total_weight[index] += total_weight_thread[thread_num][index];
        }
    }
    
    // normalize the correlation
    for (int index =  0; index < num_points_interpolation; index ++){
        // check that the weight is not zero
        if (total_weight[index] == 0.0){
            std::cerr << "Warning : In compute_projection_correction : Index " << index;
            std::cerr << " shows zero weight. Consider reducing num_points_interpolation." << std::endl;
        }
        else{
            mean_delta[index] /= total_weight[index];
        }
    }
    
    // save results
    std::string filename = input.lya_projection_correction();
    std::cout << "Saving results to " << filename << std::endl;
    std::ofstream file;
    file.open(filename.c_str(),std::ofstream::trunc); // opens the file erasing the previous contents
    if (file.is_open()){
        // print header
        file << "z mean_delta" << std::endl;
        // print results
        for (size_t index = 0; index < z_mean_delta.size(); index ++){
            file << z_mean_delta[index] << " " << mean_delta[index] <<  std::endl;
        }
        
        file.close();
    }
    else{
        std::cerr << "Error : In compute_projection_correction : Unable to open file:" << std::endl << filename << std::endl;
    }
    
    
    // display time required to run the program
    if (flag_verbose_main >= 1){
        std::cout << "End of program" << std::endl;
    }
    time(&end_time);
    double time_spent = difftime(end_time, start_time);
    if (flag_verbose_main >= 1){
        if (time_spent < 60.0){
            std::cout << "Program lasted " << time_spent << " seconds" << std::endl;
        }
        else if (time_spent < 3600.0){
            std::cout << "Program lasted " << time_spent/60.0 << " minutes" << std::endl;
        }
        else{
            std::cout << "Program lasted " << time_spent/3600.0 << " hours" << std::endl;
        }
    }
    return 0;
}