示例#1
0
TEST_F(HashTableTest, TestMapRehashWithObjects)
{
    capu::HashTable<SomeClass, capu::uint32_t> table(2);
    SomeClass c1(1);
    SomeClass c2(2);
    SomeClass c3(3);
    SomeClass c4(4);

    table.put(c1, 1);
    table.put(c2, 2);
    table.put(c3, 3);
    table.put(c4, 4); // rehashing

    SomeClass cTest(3); // same i value as c3 -> 3 must get returned
    EXPECT_EQ(3u, table.at(cTest));
}
示例#2
0
void xPerform_Fit_Bound_Simplex(const XVECTOR &i_vLower_Bound,const XVECTOR &i_vUpper_Bound, const XVECTOR & i_lpvFit_Threshold, QFunctionV i_fUser_Function, XVECTOR & o_vResult, void * i_lpvUser_Data, const char * i_lpszCache_Filename)
{
	unsigned int uiNum_Parameters = i_vLower_Bound.Get_Size();
	if (uiNum_Parameters != i_vUpper_Bound.Get_Size() || uiNum_Parameters != i_lpvFit_Threshold.Get_Size())
		fprintf(stderr,"xPerform_Fit_Bound: bound and theshold size doesn't match\n");
	else
	{
		double	dFit_Min = DBL_MAX;
		double	*lpdFit;
		unsigned int uiNum_Points = uiNum_Parameters + 1;
		// define tetrahedron spanning the search space
		XVECTOR *lpcTest_Points;
		XVECTOR cCentroid(uiNum_Parameters);
		XVECTOR cTestOuter(uiNum_Parameters);
		XVECTOR cTestInner(uiNum_Parameters);
		XVECTOR cTest(uiNum_Parameters);
		XVECTOR cDelta(uiNum_Parameters);
		XVECTOR cBounds[2];
		double dTest_Fit = 0.0;
		unsigned int uiNum_Vertices;

		lpcTest_Points = new XVECTOR[uiNum_Points];
		lpdFit = new double[uiNum_Points];

		if (i_lpszCache_Filename && !ReadPointsCache(i_lpszCache_Filename,lpcTest_Points,uiNum_Vertices,uiNum_Parameters,lpdFit))
		{
			lpcTest_Points[0] = i_vLower_Bound;
			for (unsigned int uiI = 1; uiI < uiNum_Points; uiI++)
			{
				lpcTest_Points[uiI] = i_vLower_Bound;
				lpcTest_Points[uiI].Set(uiI - 1,i_vUpper_Bound.Get(uiI - 1));
			}
			cBounds[0] = i_vLower_Bound;
			cBounds[1] = i_vUpper_Bound;

			for (unsigned int uiI = 0; uiI < uiNum_Points; uiI++)
			{
				fprintf(stdout,"-");
				fflush(stdout);
				lpdFit[uiI] = i_fUser_Function(lpcTest_Points[uiI],i_lpvUser_Data);
			}
			SavePointsCache(i_lpszCache_Filename,lpcTest_Points,uiNum_Points,uiNum_Parameters,lpdFit);
		}
		unsigned int uiFit_Max_Point = 0;
		// The method used below is basically simplex optimization, with a few modifications to handle bad data points and a contrained parameter space
//		while ((uiFit_Max_Point < uiNum_Parameters) && !Convergence(lpcTest_Points, uiNum_Parameters , i_lpvFit_Threshold))
		while (!Convergence(lpcTest_Points, uiNum_Parameters , i_lpvFit_Threshold))
		{
			fprintf(stdout,".");
			fflush(stdout);
	//		fprintf(stdout,"F: %.1f %.1f %.1f %.1f %.1f %.1f %.1f\n",cConvergence_Fault.Get(0),cConvergence_Fault.Get(1),cConvergence_Fault.Get(2),cConvergence_Fault.Get(3),cConvergence_Fault.Get(4),cConvergence_Fault.Get(5),cConvergence_Fault.Get(6));

			// Test for uniform field
			bool bIdentical = true;
			for (unsigned int uiI = 0; uiI < uiNum_Points && bIdentical; uiI++)
			{
				for (unsigned int uiJ = uiI; uiJ < uiNum_Points && bIdentical; uiJ++)
				{
					bIdentical &= fabs(lpdFit[uiI] - lpdFit[uiJ]) < 1.0e-8;
				}
			}
			if(bIdentical)
				uiFit_Max_Point++;
			else
			{
				// Find point with worst fit
				double	dFit_Max = 0.0;
				for (unsigned int uiI = 0; uiI < uiNum_Points; uiI++)
				{
					if (lpdFit[uiI] > dFit_Max)
					{
						dFit_Max = lpdFit[uiI];
						uiFit_Max_Point = uiI;
					}
				}
			}
	//		fprintf(stdout,"%i",uiFit_Max_Point);
	//		fprintf(stdout,"F: %.8e %.8e %.8e %.8e %.8e %.8e %.8e\n",dFit[0],dFit[1],dFit[2],dFit[3],dFit[4],dFit[5],dFit[6],dFit[7]);
			if (uiFit_Max_Point < uiNum_Points)
			{
				// Compute centroid of remaining parameters
				for (unsigned int uiI = 0; uiI < cCentroid.Get_Size(); uiI++)
					cCentroid.Set(uiI,0.0);

				for (unsigned int uiI = 0; uiI < uiNum_Points; uiI++)
				{
					if (uiI != uiFit_Max_Point)
						cCentroid += lpcTest_Points[uiI];
				}
				cCentroid /= (double)(uiNum_Points - 1);
				// Generate new test position
				double	dFit_Min = DBL_MAX;
				for (unsigned int uiI = 0; uiI < uiNum_Points; uiI++)
				{
					if (lpdFit[uiI] < dFit_Min)
					{
						dFit_Min = lpdFit[uiI];
					}
				}

				double	dMod = -0.5;
				double	dMod_Lcl;
				XVECTOR cDelta = lpcTest_Points[uiFit_Max_Point] - cCentroid;
				XVECTOR cDeltaTemp;
				double dFit_Test;
				XVECTOR cTest;
				if (Convergence_Point(cDelta , i_lpvFit_Threshold))
				{
	//				fprintf(stdout,"C");
					fflush(stdout);
					do
					{
						fprintf(stdout,"*");
						fflush(stdout);
						// The test point has moved to the centroid.  This is bad.  Let's try jitter
						for(unsigned int uiI = 0; uiI < uiNum_Points; uiI++)
						{
							lpcTest_Points[uiFit_Max_Point].Set(uiI,(i_vUpper_Bound.Get(uiI) + i_vLower_Bound.Get(uiI)) * xrand_d());
						}
	//					fprintf(stdout,"S: %.1f %.1f %.1f %.1f %.1f %.1f %.1f\n",cTest_Points[uiFit_Max_Point].Get(0),cTest_Points[uiFit_Max_Point].Get(1),cTest_Points[uiFit_Max_Point].Get(2),cTest_Points[uiFit_Max_Point].Get(3),cTest_Points[uiFit_Max_Point].Get(4),cTest_Points[uiFit_Max_Point].Get(5),cTest_Points[uiFit_Max_Point].Get(6));
						fflush(stdout);
						lpdFit[uiFit_Max_Point] = i_fUser_Function(lpcTest_Points[uiFit_Max_Point],i_lpvUser_Data);
					} while (isnan(lpdFit[uiFit_Max_Point]) || isinf(lpdFit[uiFit_Max_Point]));
				}
				else
				{
					do
					{
						dMod *= 2; // this is intended - first test point is -1
						dMod_Lcl = dMod;
						do
						{
		//					fprintf(stdout,",");
		//					fflush(stdout);
							cDeltaTemp = cDelta;
		//					fprintf(stdout,"S: %.1f %.1f %.1f %.1f %.1f %.1f %.1f\n",cTest_Points[uiFit_Max_Point].Get(0),cTest_Points[uiFit_Max_Point].Get(1),cTest_Points[uiFit_Max_Point].Get(2),cTest_Points[uiFit_Max_Point].Get(3),cTest_Points[uiFit_Max_Point].Get(4),cTest_Points[uiFit_Max_Point].Get(5),cTest_Points[uiFit_Max_Point].Get(6));
		//					fprintf(stdout,"C: %.1f %.1f %.1f %.1f %.1f %.1f %.1f\n",cCentroid.Get(0),cCentroid.Get(1),cCentroid.Get(2),cCentroid.Get(3),cCentroid.Get(4),cCentroid.Get(5),cCentroid.Get(6));
		//					fprintf(stdout,"D: %.1f %.1f %.1f %.1f %.1f %.1f %.1f\n",cDeltaTemp.Get(0),cDeltaTemp.Get(1),cDeltaTemp.Get(2),cDeltaTemp.Get(3),cDeltaTemp.Get(4),cDeltaTemp.Get(5),cDeltaTemp.Get(6));
							cDeltaTemp *= dMod_Lcl;
		//					fprintf(stdout,"D: %.1f %.1f %.1f %.1f %.1f %.1f %.1f\n",cDeltaTemp.Get(0),cDeltaTemp.Get(1),cDeltaTemp.Get(2),cDeltaTemp.Get(3),cDeltaTemp.Get(4),cDeltaTemp.Get(5),cDeltaTemp.Get(6));
							cTest = cCentroid + cDeltaTemp;
		//					fprintf(stdout,"T: %.1f %.1f %.1f %.1f %.1f %.1f %.1f\n",cTest.Get(0),cTest.Get(1),cTest.Get(2),cTest.Get(3),cTest.Get(4),cTest.Get(5),cTest.Get(6));
		//					sleep(1);
							dMod_Lcl += .125;
							if (dMod_Lcl == 0.0)
								dMod_Lcl += 0.50; // make sure we don't use the centroid itself!
						}
						while (!BoundTest(cTest,cBounds) && dMod_Lcl < 1.0);
						dMod_Lcl += 0.125; // raise back to previous test value
						fprintf(stdout,"%%");
						fflush(stdout);
						dFit_Test = i_fUser_Function(cTest,i_lpvUser_Data);
					}
					while (dFit_Test < dFit_Min && dMod_Lcl == dMod);
					if (dFit_Test >= lpdFit[uiFit_Max_Point])
					{
						cTest = cCentroid + cDelta * 0.5;
						dFit_Test = i_fUser_Function(cTest,i_lpvUser_Data);
						fprintf(stdout,"#");
						fflush(stdout);
					}

					if (dFit_Test <= lpdFit[uiFit_Max_Point])
					{
		//				fprintf(stdout,";");
	//					fflush(stdout);
						lpdFit[uiFit_Max_Point] = dFit_Test;
						lpcTest_Points[uiFit_Max_Point] = cTest;
					}
					else
					{
						// no success; contract the simplex
						// Compute centroid 
						for (unsigned int uiI = 0; uiI < cCentroid.Get_Size(); uiI++)
							cCentroid.Set(uiI,0.0);

						for (unsigned int uiI = 0; uiI < uiNum_Points; uiI++)
						{
							cCentroid += lpcTest_Points[uiI];
						}
						cCentroid /= (double)(uiNum_Points);
						// Scale the simplex by 1/2
						for (unsigned int uiI = 0; uiI < uiNum_Points; uiI++)
						{
							cDelta = lpcTest_Points[uiI] - cCentroid;
							lpcTest_Points[uiI] = cCentroid + 0.5 * cDelta;
							lpdFit[uiI] = i_fUser_Function(lpcTest_Points[uiI],i_lpvUser_Data);
							fprintf(stdout,"-");
							fflush(stdout);
						}
					}
				}
			}
			SavePointsCache(i_lpszCache_Filename,lpcTest_Points,uiNum_Points,uiNum_Parameters,lpdFit);
		}

		for (unsigned int uiI = 0; uiI < cCentroid.Get_Size(); uiI++)
			cCentroid.Set(uiI,0.0);
		for (unsigned int uiI = 0; uiI < uiNum_Points; uiI++)
		{
			cCentroid += lpcTest_Points[uiI];
		}
		cCentroid /= (double)(uiNum_Points);

		o_vResult = cCentroid;
	}
}
int main(int i_iArg_Count,const char * i_lpszArg_Values[])
{
//	char lpszLine_Buffer[1024];
	xrand_Set_Type(XRT_K);
	xrsrand();

	char	lpszFilename[64];
	char	lpszBuffer[1024];
	XDATASET cDataSource;
	XDATASET cOpacity_Map_Shell;
	XDATASET cOpacity_Map_Ejecta;
	char	chSeparator;
	if (i_iArg_Count < 4)
	{
		Usage("Missing parameters");
	}
	else
	{
		// generate the target spectrum
        ES::Spectrum cTarget = ES::Spectrum::create_from_ascii_file( i_lpszArg_Values[1] );
		double	dMin_WL,dMax_WL;
		unsigned int uiIon;


		// default to full range

		if (strcmp(i_lpszArg_Values[2],"CaNIR") == 0)
		{
			uiIon = 2001;
			dMin_WL = 7000.0;
			dMax_WL = 8300.0;
		}
		else if (strcmp(i_lpszArg_Values[2],"CaHK") == 0)
		{
			uiIon = 2001;
			dMin_WL = 3000.0;
			dMax_WL = 4300.0;
		}
		else if (strcmp(i_lpszArg_Values[2],"Si6355") == 0)
		{
			uiIon = 1401;
			dMin_WL = 5200.0;
			dMax_WL = 6500.0;
		}
		else //if (strcmp(i_lpszArg_Values[2],"Full") != 0)
		{
			uiIon = 0;
			dMin_WL = -1;
			dMax_WL = -1;
		}
//		else
//		{
//			uiIon = 2001; // need to decide how to handle this case
//			dMin_WL = cTarget.wl(0);
//			dMax_WL = cTarget.wl(target.size() - 1);
//		}
		if (dMin_WL < cTarget.wl(0) || dMax_WL > cTarget.wl(cTarget.size() - 1))
		{
			Usage("Source spectrum does not cover desired range");
		}
		else if (dMin_WL > 0 && dMax_WL > 0)
		{
			ES::Spectrum cOutput  = ES::Spectrum::create_from_range_and_size( cTarget.wl(0), cTarget.wl(cTarget.size() - 1), cTarget.size());
			ES::Spectrum cBest_Fit_Output  = ES::Spectrum::create_from_range_and_size( cTarget.wl(0), cTarget.wl(cTarget.size() - 1), cTarget.size());
			bool bChi2 = ValidateChi2(cTarget,dMin_WL, dMax_WL);
			double	dBest_Fit = DBL_MAX;
			double	dBest_Fit_PS_Ion_Temp, dBest_Fit_PS_Temp, dBest_Fit_Day, dBest_Fit_PS_Log_Tau, dBest_Fit_HVF_Ion_Temp, dBest_Fit_PS_Vel, dBest_Fit_HVF_Log_Tau;
			bool bRestart = false;
			int iBest_Fit_File;
			const char * lpszBest_Fit_File;
			bool bBest_Fit_With_Shell;
			char lpszOpacity_File_Ejecta[64], lpszOpacity_File_Shell[64];
			char lpszOutput_Filename[128];
			char lpszTitle[128];
			FILE * fileCache = fopen("spectrafit.filelist.cache","rt");
			unsigned int uiStartFile = 3;
			if (fileCache)
			{
				char lpszBuffer[256];
				fgets(lpszBuffer,256,fileCache);
				uiStartFile = atoi(lpszBuffer);
				fgets(lpszBuffer,256,fileCache);
				unsigned int uiNumFiles = atoi(lpszBuffer);
				bool bListTest = false;
				if (uiNumFiles == i_iArg_Count - 3)
				{
					bListTest = true;
					bRestart = true;
					for (unsigned int uiI = 1; uiI < i_iArg_Count && bListTest; uiI++)
					{
						fgets(lpszBuffer,256,fileCache);
						// need to strip CR/LF
						char * lpszCursor = lpszBuffer;
						lpszCursor += strlen(lpszBuffer);
						lpszCursor--;
						if (lpszCursor[0] == 10 || lpszCursor[0] == 13)
							lpszCursor[0] = 0;
						lpszCursor--;
						if (lpszCursor[0] == 10 || lpszCursor[0] == 13)
							lpszCursor[0] = 0;
						bListTest = (strcmp(lpszBuffer,i_lpszArg_Values[uiI]) == 0);
					}
					fgets(lpszBuffer,256,fileCache);
					dBest_Fit = atof(lpszBuffer);
					fgets(lpszBuffer,256,fileCache);
					dBest_Fit_PS_Ion_Temp = atof(lpszBuffer);
					fgets(lpszBuffer,256,fileCache);
					dBest_Fit_PS_Temp = atof(lpszBuffer);
					fgets(lpszBuffer,256,fileCache);
					dBest_Fit_Day = atof(lpszBuffer);
					fgets(lpszBuffer,256,fileCache);
					dBest_Fit_PS_Log_Tau = atof(lpszBuffer);
					fgets(lpszBuffer,256,fileCache);
					dBest_Fit_HVF_Ion_Temp = atof(lpszBuffer);
					fgets(lpszBuffer,256,fileCache);
					dBest_Fit_PS_Vel = atof(lpszBuffer);
					fgets(lpszBuffer,256,fileCache);
					dBest_Fit_HVF_Log_Tau = atof(lpszBuffer);
					fgets(lpszBuffer,256,fileCache);
					int iBest_Fit_File = atoi(lpszBuffer);
					lpszBest_Fit_File = i_lpszArg_Values[iBest_Fit_File];
					fgets(lpszBuffer,256,fileCache);
					bBest_Fit_With_Shell = lpszBuffer[0] == 't';
					printf("Generating spectra\n");
					// Generate the output for current best fit
					XVECTOR cTest(7);
					for (unsigned int uiI = 1; uiI < cOpacity_Map_Ejecta.GetNumColumns(); uiI++)
						if (cOpacity_Map_Ejecta.GetElement(uiI,0) == dBest_Fit_Day)
							cTest.Set(0,uiI); // time
					cTest.Set(1,dBest_Fit_PS_Vel); // PS velocity (kkm/s)
					cTest.Set(2,dBest_Fit_PS_Temp); // PS temp (kK)
					cTest.Set(3,dBest_Fit_PS_Ion_Temp); // PS ion temp (kK)
					cTest.Set(4,dBest_Fit_PS_Log_Tau); // PS ion log opacity scaling
					cTest.Set(5,dBest_Fit_HVF_Ion_Temp); // HVF ion temp (kK)
					cTest.Set(6,dBest_Fit_HVF_Log_Tau); // HVF ion log opacity scaling

					sprintf(lpszOpacity_File_Ejecta,"%s/opacity_map_ejecta.xdataset",i_lpszArg_Values[iBest_Fit_File]);
					sprintf(lpszOpacity_File_Shell,"%s/opacity_map_shell.xdataset",i_lpszArg_Values[iBest_Fit_File]);
					cOpacity_Map_Ejecta.ReadDataFileBin(lpszOpacity_File_Ejecta);
					cOpacity_Map_Shell.ReadDataFileBin(lpszOpacity_File_Shell);
					Generate_Synow_Spectra(cTarget, cOpacity_Map_Ejecta,cOpacity_Map_Shell,uiIon,cTest,cBest_Fit_Output);
					printf("Done\n");
				}
				

				if (!bListTest)
				{
					uiStartFile = 3; // different file list - restart.
					system("rm spectrafit.filelist.cache");
//					system("rm spectrafit.*.cache");
					dBest_Fit = DBL_MAX;
				}
				fclose(fileCache);
			}
				
			for (unsigned int uiI = uiStartFile; uiI < i_iArg_Count; uiI++)
			{
				bRestart = false;
				printf("Reading %s",i_lpszArg_Values[uiI]);
				sprintf(lpszOpacity_File_Ejecta,"%s/opacity_map_ejecta.xdataset",i_lpszArg_Values[uiI]);
				sprintf(lpszOpacity_File_Shell,"%s/opacity_map_shell.xdataset",i_lpszArg_Values[uiI]);
				cOpacity_Map_Ejecta.ReadDataFileBin(lpszOpacity_File_Ejecta);
				cOpacity_Map_Shell.ReadDataFileBin(lpszOpacity_File_Shell);
				if (cOpacity_Map_Ejecta.GetNumElements() > 0)
				{
					double dDay,dPS_Vel, dPS_Temp,dPS_Ion_Temp,dPS_Log_Tau,dHVF_Ion_Temp,dHVF_Log_Tau;
					double dFit = CompareFits(i_lpszArg_Values[uiI], cTarget, cOpacity_Map_Ejecta,cOpacity_Map_Shell, uiIon, dMin_WL, dMax_WL, bChi2, dDay, dPS_Vel, dPS_Temp, dPS_Ion_Temp, dPS_Log_Tau, dHVF_Ion_Temp, dHVF_Log_Tau, cOutput);
					if (dFit != -1.0 && dFit < dBest_Fit)
					{
						dBest_Fit = dFit;
						dBest_Fit_Day = dDay;
						dBest_Fit_PS_Temp = dPS_Temp;
						dBest_Fit_PS_Vel = dPS_Vel;
						dBest_Fit_PS_Log_Tau = dPS_Log_Tau;
						dBest_Fit_PS_Ion_Temp = dPS_Ion_Temp;
						dBest_Fit_HVF_Log_Tau = dHVF_Log_Tau;
						dBest_Fit_HVF_Ion_Temp = dHVF_Ion_Temp;
						bBest_Fit_With_Shell = (cOpacity_Map_Shell.GetNumElements() > 0);
						cBest_Fit_Output = cOutput;
						lpszBest_Fit_File = i_lpszArg_Values[uiI];
						iBest_Fit_File = uiI;
					}
					if (bChi2)
						printf("\tChi^2 Fit = %.2e\n",dFit);
					else
						printf("\tVar   Fit = %.2e\n",dFit);
				}
				else
					printf("Invalid file\n");
				fileCache = fopen("spectrafit.filelist.cache","wt");
				fprintf(fileCache,"%i\n",uiI);
				fprintf(fileCache,"%i\n",i_iArg_Count - 3);
				for (unsigned int uiJ = 1; uiJ < i_iArg_Count; uiJ++)
					fprintf(fileCache,"%s\n",i_lpszArg_Values[uiJ]);
				fprintf(fileCache,"%.17e\n",dBest_Fit);
				fprintf(fileCache,"%.17e\n",dBest_Fit_PS_Ion_Temp);
				fprintf(fileCache,"%.17e\n",dBest_Fit_PS_Temp);
				fprintf(fileCache,"%.17e\n",dBest_Fit_Day);
				fprintf(fileCache,"%.17e\n",dBest_Fit_PS_Log_Tau);
				fprintf(fileCache,"%.17e\n",dBest_Fit_HVF_Ion_Temp);
				fprintf(fileCache,"%.17e\n",dBest_Fit_PS_Vel);
				fprintf(fileCache,"%.17e\n",dBest_Fit_HVF_Log_Tau);
				fprintf(fileCache,"%i\n",iBest_Fit_File);
				fprintf(fileCache,"%c\n",bBest_Fit_With_Shell ? 't' : 'f');
				fclose(fileCache);
			}
			//system("rm spectrafit.filelist.cache");// done - delete the cache
			fprintf(stdout,"spectrafit v%s\n",VERSION);
			if (bChi2)
				fprintf(stdout,"Minimum chi^2: %.3e\n", dBest_Fit, lpszBest_Fit_File);
			else
				fprintf(stdout,"Minimum variance: %.3e", dBest_Fit, lpszBest_Fit_File);
			fprintf(stdout,"model: %s\n",lpszBest_Fit_File);
			fprintf(stdout,"Day: %.2f\n",dBest_Fit_Day);
			fprintf(stdout,"PS Vel: %.2f\n",dBest_Fit_PS_Vel);
			fprintf(stdout,"PS Temp: %.2f\n",dBest_Fit_PS_Temp);
			fprintf(stdout,"PS Log Tau: %.2f\n",dBest_Fit_PS_Log_Tau);
			fprintf(stdout,"PS Ion Temp: %.2f\n",dBest_Fit_PS_Ion_Temp);
			if (bBest_Fit_With_Shell)
			{
				fprintf(stdout,"HVF Log Tau: %.2f\n",dBest_Fit_HVF_Log_Tau);
				fprintf(stdout,"HVF Ion Temp: %.2f\n",dBest_Fit_HVF_Ion_Temp);
			}
			sprintf(lpszOutput_Filename,"%s.bestfit.eps",i_lpszArg_Values[1]);
			if (bBest_Fit_With_Shell)
				sprintf(lpszTitle,"%s: d %.2f Vps %.1f Tps %.1f tps %.2f Tpsi %.2f thv %.2f Thv %.2f",lpszBest_Fit_File,dBest_Fit_Day,dBest_Fit_PS_Vel,dBest_Fit_PS_Temp,dBest_Fit_PS_Log_Tau,dBest_Fit_PS_Ion_Temp,dBest_Fit_HVF_Log_Tau,dBest_Fit_HVF_Ion_Temp);
			else
				sprintf(lpszTitle,"%s: d %.2f Vps %.1f Tps %.1f tps %.2f Tpsi %.2f",lpszBest_Fit_File,dBest_Fit_Day,dBest_Fit_PS_Vel,dBest_Fit_PS_Temp,dBest_Fit_PS_Log_Tau,dBest_Fit_PS_Ion_Temp);
			Plot(cTarget, cBest_Fit_Output, lpszOutput_Filename, dMin_WL, dMax_WL, lpszTitle);
			fprintf(stdout,"Best fit output to %s.\n",lpszOutput_Filename);
		}
		else
		{
			Usage("Invalid fit region");
		}
	}
	return 0;
}
示例#4
0
void xPerform_Fit_Bound(const XVECTOR &i_vLower_Bound,const XVECTOR &i_vUpper_Bound, const XVECTOR & i_lpvFit_Threshold, QFunctionV i_fUser_Function, XVECTOR & o_vResult, void * i_lpvUser_Data, const char * i_lpszCache_Filename)
{
	// use the following define to set the numberr of dimensions to test - value should be # dim + 1 (e.g. 3-d = 4 points)
	
	unsigned int uiNum_Parameters = i_vLower_Bound.Get_Size();
	if (uiNum_Parameters != i_vUpper_Bound.Get_Size() || uiNum_Parameters != i_lpvFit_Threshold.Get_Size())
		fprintf(stderr,"xPerform_Fit_Bound: bound and theshold size doesn't match\n");
	else
	{
		double	dFit_Min = DBL_MAX;
		double	*lpdFit;
		// define tetrahedron spanning the search space
		XVECTOR *lpcTest_Points;
		XVECTOR cCentroid(uiNum_Parameters);
		XVECTOR cTestOuter(uiNum_Parameters);
		XVECTOR cTestInner(uiNum_Parameters);
		XVECTOR cTest(uiNum_Parameters);
		XVECTOR cDelta(uiNum_Parameters);
		double dTest_Fit = 0.0;
		unsigned int uiNum_Vertices;

		uiNum_Vertices = 1 << uiNum_Parameters;
		lpcTest_Points = new XVECTOR[uiNum_Vertices];
		lpdFit = new double[uiNum_Vertices];

		for (unsigned int uiI = 0; uiI < uiNum_Vertices; uiI++)
			lpcTest_Points[uiI].Set_Size(uiNum_Parameters);

		double	dFit_Sum = 0.0;
		if (i_lpszCache_Filename == NULL || !ReadPointsCache(i_lpszCache_Filename,lpcTest_Points,uiNum_Vertices,uiNum_Parameters,lpdFit))
		{
			// create a cuboid that spans the search space
			for (unsigned int uiI = 0; uiI < uiNum_Vertices; uiI++)
			{
				lpcTest_Points[uiI] = i_vLower_Bound;
				for (unsigned int uiJ = 0; uiJ < uiNum_Parameters; uiJ++)
				{
					if (uiI & (1 << uiJ)) 
						lpcTest_Points[uiI].Set(uiJ,i_vUpper_Bound.Get(uiJ));
				}
			}
			for (unsigned int uiI = 0; uiI < uiNum_Vertices; uiI++)
			{
				cCentroid += lpcTest_Points[uiI];
				dFit_Sum ++;
			}
			cCentroid /= dFit_Sum;
	//		printf("Centroid\n");
		//	cCentroid.Print();
	
			// Make sure the centroid produces a valid spectrum - if not, randomly generate a point within the search space to act as the centroid for the time being...
			// This centroid is going to be used to adjust edges of the cuboid to have a valid fit
			double dCentroid_Fit = 0.0;
			do
			{
				fprintf(stdout,".");
				fflush(stdout);
				if (isnan(dCentroid_Fit) || isinf(dCentroid_Fit)) // need a different point - try random point within the grid
				{
					cDelta = i_vUpper_Bound - i_vLower_Bound;
					for (unsigned int uiI = 0; uiI < uiNum_Parameters; uiI++)
					{
						cCentroid.Set(uiI,i_vLower_Bound.Get(uiI) + xrand_d() * cDelta.Get(uiI));
					}
				}
				dCentroid_Fit = i_fUser_Function(cCentroid,i_lpvUser_Data);
			}
			while (isnan(dCentroid_Fit) || isinf(dCentroid_Fit));
	
			for (unsigned int uiI = 0; uiI < uiNum_Vertices; uiI++)
			{
				fprintf(stdout,"-");
				fflush(stdout);
				lpdFit[uiI] = i_fUser_Function(lpcTest_Points[uiI],i_lpvUser_Data);
				cTestOuter = lpcTest_Points[uiI];
				cTest = lpcTest_Points[uiI];
				while(isnan(lpdFit[uiI]) || isinf(lpdFit[uiI]))
				{
					fprintf(stdout,"_");
					fflush(stdout);
					XVECTOR cDelta = cTestOuter - cCentroid;
					cDelta *= 0.5;
					cTest = cCentroid + cDelta;
		//			cTest.Print();
					lpdFit[uiI] = i_fUser_Function(cTest,i_lpvUser_Data);
					cTestOuter = cTest;
				}
				lpcTest_Points[uiI] = cTest;
			}

			SavePointsCache(i_lpszCache_Filename,lpcTest_Points,uiNum_Vertices,uiNum_Parameters,lpdFit);
		}
		unsigned int uiFit_Max_Point = uiNum_Vertices;
		unsigned int uiFit_Min_Point = uiNum_Vertices;
	
		while (!Convergence(lpcTest_Points, uiNum_Vertices , i_lpvFit_Threshold))
		{
			fprintf(stdout,"+");
			fflush(stdout);
	//		fprintf(stdout,"F: %.1f %.1f %.1f %.1f %.1f %.1f %.1f\n",cConvergence_Fault.Get(0),cConvergence_Fault.Get(1),cConvergence_Fault.Get(2),cConvergence_Fault.Get(3),cConvergence_Fault.Get(4),cConvergence_Fault.Get(5),cConvergence_Fault.Get(6));

			// Find point with worst fit
			double	dFit_Max = 0.0;
			double	dFit_Near_Max = 0.0;
			double	dFit_Min = DBL_MAX;
			double	dFit_Variance = 0.0;
			double	dFit_Mean = 0.0;
			bool	bClose_Fit = true;
			uiFit_Max_Point = uiNum_Vertices;
			uiFit_Min_Point = uiNum_Vertices;
			for (unsigned int uiI = 0; uiI < uiNum_Vertices; uiI++)
			{
	//			printf("%i : %.2e\n",uiI,lpdFit[uiI]);
				dFit_Variance += lpdFit[uiI] * lpdFit[uiI];
				dFit_Mean += lpdFit[uiI];
				if (lpdFit[uiI] > dFit_Max)
				{
					dFit_Max = lpdFit[uiI];
					uiFit_Max_Point = uiI;
				}
				if (lpdFit[uiI] < dFit_Min)
				{
					dFit_Min = lpdFit[uiI];
					uiFit_Min_Point = uiI;
				}
			}
			if (dFit_Min <= 0.5)
			{
				for (unsigned int uiI = 0; uiI < uiNum_Vertices; uiI++)
				{
					lpdFit[uiI] = lpdFit[uiFit_Min_Point];
					lpcTest_Points[uiI] = lpcTest_Points[uiFit_Min_Point];
				}
			}
			else
			{
				dFit_Variance /= uiNum_Vertices;
				dFit_Mean /= uiNum_Vertices;
				double dFit_Std_Dev = dFit_Variance - dFit_Mean * dFit_Mean;
	//			for (unsigned int uiI = 0; uiI < uiNum_Vertices && bClose_Fit; uiI++)
	//			{
	//				bClose_Fit = (fabs(lpdFit[uiI] - dFit_Mean) < (2.0 * dFit_Std_Dev));
	//			}
	//			bClose_Fit |= (dFit_Std_Dev < 10.0);
				bClose_Fit &= (dFit_Std_Dev < 10.0);
				if (dFit_Near_Max == 0.0)
				{
					for (unsigned int uiI = 0; uiI < uiNum_Vertices; uiI++)
					{
						if (lpdFit[uiI] > dFit_Near_Max && uiI != uiFit_Max_Point)
							dFit_Near_Max = lpdFit[uiI];
					}
				}
		//		fprintf(stdout,"%i",uiFit_Max_Point);
		//		fprintf(stdout,"F: %.8e %.8e %.8e %.8e %.8e %.8e %.8e\n",dFit[0],dFit[1],dFit[2],dFit[3],dFit[4],dFit[5],dFit[6],dFit[7]);
		//		if (uiFit_Max_Point < uiNum_Vertices)
				{
					// Compute weighted centroid of remaining parameters
					for (unsigned int uiI = 0; uiI < cCentroid.Get_Size(); uiI++)
						cCentroid.Set(uiI,0.0);
					dFit_Sum = 0.0;
					for (unsigned int uiI = 0; uiI < uiNum_Vertices; uiI++)
					{
						if (uiI != uiFit_Max_Point)
						{
							XVECTOR cTemp = lpcTest_Points[uiI];
		//					lpcTest_Points[uiI].Print(NULL);
		//					cTemp.Print(NULL);
							if (lpdFit[uiI] > 1.0)
								cTemp *= lpdFit[uiI];
							cCentroid += cTemp;
		//					cCentroid.Print(NULL);
							if (lpdFit[uiI] > 1.0)
								dFit_Sum += lpdFit[uiI];
							else
								dFit_Sum += 1.0;
						}
					}
					cCentroid /= dFit_Sum;
		//			printf("Centroid\n");
		//			for (unsigned int uiI = 0; uiI < uiNum_Parameters; uiI++)
		//			{
		//				printf("%.1f\n",cCentroid.Get(uiI));
		//			}
					cTestOuter = lpcTest_Points[uiFit_Max_Point];
					cTestInner = cCentroid;
	//				printf("\n");
	//				cCentroid.Print();
					dTest_Fit = i_fUser_Function(cCentroid,i_lpvUser_Data);
					if (bClose_Fit && !isnan(dTest_Fit) && !isinf(dTest_Fit))
					{
						for (unsigned int uiI = 0; uiI < uiNum_Vertices; uiI++)
						{
	//						fprintf(stdout,"-%.0f\t%.2e\t%.0f\t%.0f\t%c\t%.1f\n",dTest_Fit,dFit_Min,dFit_Max,dFit_Near_Max,bClose_Fit ? 't' : 'f',dFit_Std_Dev);
							fprintf(stdout,"-");
							fflush(stdout);
							cDelta = cCentroid - lpcTest_Points[uiI];
							cDelta *= 0.5;
							lpcTest_Points[uiI] += cDelta;
							lpdFit[uiI] = i_fUser_Function(lpcTest_Points[uiI],i_lpvUser_Data);
						}
					}
					else if (dTest_Fit > dFit_Near_Max)
					{
						cTestOuter = cCentroid;
						cTestInner = lpcTest_Points[uiFit_Min_Point];
						cTest = cTestInner;
						while (isnan(dTest_Fit) || isinf(dTest_Fit) || dTest_Fit > dFit_Near_Max)
						{
							//cCentroid.Print();
	//						fprintf(stdout,"@%.0f\t%.2e\t%.0f\t%.0f\t%c\t%.1f\n",dTest_Fit,dFit_Min,dFit_Max,dFit_Near_Max,bClose_Fit ? 't' : 'f',dFit_Std_Dev);
							fprintf(stdout,"@");
							fflush(stdout);
							cDelta = cTestOuter - cTestInner;
							cDelta *= 0.5;
							cTest = cTestInner + cDelta;
	//						cTest.Print();
							dTest_Fit = i_fUser_Function(cTest,i_lpvUser_Data);
							cTestOuter = cTest;
	/*						lpcTest_Points[uiFit_Max_Point] = cCentroid;
							lpdFit[uiFit_Max_Point] = dTest_Fit;
							for (unsigned int uiI = 0; uiI < cCentroid.Get_Size(); uiI++)
								cCentroid.Set(uiI,0.0);
							dFit_Sum = 0.0;
							for (unsigned int uiI = 0; uiI < uiNum_Vertices; uiI++)
							{
								XVECTOR cTemp = lpcTest_Points[uiI];
								if (lpdFit[uiI] > 1.0)
									cTemp *= lpdFit[uiI];
								cCentroid += cTemp;
								if (lpdFit[uiI] > 1.0)
									dFit_Sum += lpdFit[uiI];
								else
									dFit_Sum == 1.0;
							}
							cCentroid /= dFit_Sum;
							Generate_Synow_Spectra(i_cTarget,i_cOpacity_Map_A,i_cOpacity_Map_B,i_uiIon,cCentroid,cOutput);
							dTest_Fit = Fit(i_cTarget, cOutput, i_dMin_WL, i_dMax_WL, i_bChi2);
	*/
						}
						lpcTest_Points[uiFit_Max_Point] = cTest;
						lpdFit[uiFit_Max_Point] = dTest_Fit;
					}
					else
					{
						cTest = lpcTest_Points[uiFit_Max_Point];
						double dTest_Fit = 0.0;
						while(isnan(dTest_Fit) || isinf(dTest_Fit) || (!bClose_Fit && dTest_Fit < dFit_Min))
						{
	//						fprintf(stdout,"*%.0f\t%.2e\t%.0f\t%.0f\t%c\t%.1f\n",dTest_Fit,dFit_Min,dFit_Max,dFit_Near_Max,bClose_Fit ? 't' : 'f',dFit_Std_Dev);
							fprintf(stdout,"*");
							fflush(stdout);
							cDelta = cTestOuter - cTestInner;
							cDelta *= 0.5;
							cTest = cTestInner + cDelta;
	//						cTest.Print();
							dTest_Fit = i_fUser_Function(cTest,i_lpvUser_Data);
							cTestInner = cTest;
						}
						cTestOuter = cTest;
						cTestInner = cCentroid;
						while(isnan(dTest_Fit) || isinf(dTest_Fit) || dTest_Fit == 0.0 || dTest_Fit > dFit_Near_Max)
						{
	//						fprintf(stdout,"%%%.0f\t%.2e\t%.0f\t%.0f\t%c\t%.1f\n",dTest_Fit,dFit_Min,dFit_Max,dFit_Near_Max,bClose_Fit ? 't' : 'f',dFit_Std_Dev);
							fprintf(stdout,"%%");
							fflush(stdout);
							cDelta = cTestOuter - cTestInner;
							cDelta *= 0.5;
							cTest = cTestInner + cDelta;
	//						cTest.Print();
							dTest_Fit = i_fUser_Function(cTest,i_lpvUser_Data);
							cTestOuter = cTest;
						}
						lpcTest_Points[uiFit_Max_Point] = cTest;
						lpdFit[uiFit_Max_Point] = dTest_Fit;
					}
				}
			}
			SavePointsCache(i_lpszCache_Filename,lpcTest_Points,uiNum_Vertices,uiNum_Parameters,lpdFit);
		}

	//	printf("Convergence\n");
	//	for (unsigned int uiI = 0; uiI < uiNum_Parameters; uiI++)
	//	{
	//		printf("%.1f\n",cConvergence_Fault.Get(uiI));
	//	}
		for (unsigned int uiI = 0; uiI < cCentroid.Get_Size(); uiI++)
			cCentroid.Set(uiI,0.0);
		for (unsigned int uiI = 0; uiI < uiNum_Vertices; uiI++)
		{
			cCentroid += lpcTest_Points[uiI];
		}
		cCentroid /= (double)(uiNum_Vertices);

		o_vResult = cCentroid;
	}
}
double CompareFits(const char * i_lpszFileSource, const ES::Spectrum &i_cTarget, XDATASET & i_cOpacity_Map_A, XDATASET & i_cOpacity_Map_B, unsigned int i_uiIon, const double &i_dMin_WL, const double &i_dMax_WL, bool i_bChi2, double &o_dDay, double & o_dPS_Vel, double &o_dPS_Temp, double & o_dPS_Ion_Temp, double &o_dPS_Log_Tau, double & o_dHVF_Ion_Temp, double &o_dHVF_Log_Tau, ES::Spectrum &o_cOutput)
{
	// use the following define to set the numberr of dimensions to test - value should be # dim + 1 (e.g. 3-d = 4 points)
#define NUM_PARAMETERS 7
	unsigned int uiParameters = NUM_PARAMETERS;
	ES::Spectrum cOutput  = ES::Spectrum::create_from_range_and_size( i_cTarget.wl(0), i_cTarget.wl(i_cTarget.size() - 1), i_cTarget.size());

	double	dFit_Min = DBL_MAX;
	double	*lpdFit;
	// define tetrahedron spanning the search space
	XVECTOR *lpcTest_Points;
	XVECTOR cBounds[2] = {XVECTOR(NUM_PARAMETERS),XVECTOR(NUM_PARAMETERS)};
	XVECTOR cThreshold(NUM_PARAMETERS);
	XVECTOR cCentroid(NUM_PARAMETERS);
	XVECTOR cTestOuter(NUM_PARAMETERS);
	XVECTOR cTestInner(NUM_PARAMETERS);
	XVECTOR cTest(NUM_PARAMETERS);
	XVECTOR cDelta(NUM_PARAMETERS);
	XVECTOR cConvergence_Fault(NUM_PARAMETERS);
	double dTest_Fit = 0.0;
	unsigned int uiNum_Vertices;

	cBounds[0].Set(0,0.0); // time
	cBounds[0].Set(1,5.0); // PS velocity (kkm/s)
	cBounds[0].Set(2,5.0); // PS temp (kK)
	cBounds[0].Set(3,1.0); // PS ion temp (kK)
	cBounds[0].Set(4,-10.0); // PS ion log opacity scaling
	cBounds[0].Set(5,1.0); // HVF ion temp (kK)
	cBounds[0].Set(6,-10.0); // HVF ion log opacity scaling

	cBounds[1].Set(0,i_cOpacity_Map_A.GetNumColumns() - 2); // time
	cBounds[1].Set(1,40.0); // PS velocity (kkm/s)
	cBounds[1].Set(2,30.0); // PS temp (kK)
	cBounds[1].Set(3,30.0); // PS ion temp (kK)
	cBounds[1].Set(4,10.0); // PS ion log opacity scaling
	cBounds[1].Set(5,30.0); // HVF ion temp (kK)
	cBounds[1].Set(6,-8.0); // HVF ion log opacity scaling

	cThreshold.Set(0,1.0);
	cThreshold.Set(1,0.5);
	cThreshold.Set(2,0.25);
	cThreshold.Set(3,0.5);
	cThreshold.Set(4,0.1);
	cThreshold.Set(5,0.5);
	cThreshold.Set(6,0.1);
	cThreshold.Set(7,0.5);

	if (i_cOpacity_Map_B.GetNumElements() == 0)
		uiParameters = 6; // don't look for HVF component separately

	uiNum_Vertices = 1 << uiParameters;
	lpcTest_Points = new XVECTOR[uiNum_Vertices];
	lpdFit = new double[uiNum_Vertices];

	for (unsigned int uiI = 0; uiI < uiNum_Vertices; uiI++)
		lpcTest_Points[uiI].Set_Size(NUM_PARAMETERS);

	double	dFit_Sum = 0.0;
	if (!ReadPointsCache(i_lpszFileSource,lpcTest_Points,uiNum_Vertices,uiParameters,lpdFit))
	{
		// create a cuboid that spans the search space
		for (unsigned int uiI = 0; uiI < uiNum_Vertices; uiI++)
		{
			lpcTest_Points[uiI] = cBounds[0];
			for (unsigned int uiJ = 0; uiJ < uiParameters; uiJ++)
			{
				if (uiI & (1 << uiJ)) 
					lpcTest_Points[uiI].Set(uiJ,cBounds[1].Get(uiJ));
			}
		}
		for (unsigned int uiI = 0; uiI < uiNum_Vertices; uiI++)
		{
			cCentroid += lpcTest_Points[uiI];
			dFit_Sum ++;
		}
		cCentroid /= dFit_Sum;
//		printf("Centroid\n");
	//	cCentroid.Print();
	
		// Make sure the centroid produces a valid spectrum - if not, randomly generate a point within the search space to act as the centroid for the time being...
		// This centroid is going to be used to adjust edges of the cuboid to have a valid fit
		double dCentroid_Fit = 0.0;
		do
		{
			fprintf(stdout,".");
			fflush(stdout);
			if (isnan(dCentroid_Fit) || isinf(dCentroid_Fit)) // need a different point - try random point within the grid
			{
				cDelta = cBounds[1] - cBounds[0];
				for (unsigned int uiI = 0; uiI < NUM_PARAMETERS; uiI++)
				{
					cCentroid.Set(uiI,cBounds[0].Get(uiI) + xrand_d() * cDelta.Get(uiI));
				}
			}
			Generate_Synow_Spectra(i_cTarget,i_cOpacity_Map_A,i_cOpacity_Map_B,i_uiIon,cCentroid,cOutput);
			dCentroid_Fit = Fit(i_cTarget, cOutput, i_dMin_WL, i_dMax_WL, i_bChi2);
		}
		while (isnan(dCentroid_Fit) || isinf(dCentroid_Fit));
	
		for (unsigned int uiI = 0; uiI < uiNum_Vertices; uiI++)
		{
			fprintf(stdout,"-");
			fflush(stdout);
			Generate_Synow_Spectra(i_cTarget,i_cOpacity_Map_A,i_cOpacity_Map_B,i_uiIon,lpcTest_Points[uiI],cOutput);
			lpdFit[uiI] = Fit(i_cTarget, cOutput, i_dMin_WL, i_dMax_WL, i_bChi2);
			cTestOuter = lpcTest_Points[uiI];
			cTest = lpcTest_Points[uiI];
			while(isnan(lpdFit[uiI]) || isinf(lpdFit[uiI]))
			{
				fprintf(stdout,"_");
				fflush(stdout);
				XVECTOR cDelta = cTestOuter - cCentroid;
				cDelta *= 0.5;
				cTest = cCentroid + cDelta;
	//			cTest.Print();
				Generate_Synow_Spectra(i_cTarget,i_cOpacity_Map_A,i_cOpacity_Map_B,i_uiIon,cTest,cOutput);
				lpdFit[uiI] = Fit(i_cTarget, cOutput, i_dMin_WL, i_dMax_WL, i_bChi2);
				cTestOuter = cTest;
			}
			lpcTest_Points[uiI] = cTest;
		}

		SavePointsCache(i_lpszFileSource,lpcTest_Points,uiNum_Vertices,uiParameters,lpdFit);
	}
	unsigned int uiFit_Max_Point = uiNum_Vertices;
	unsigned int uiFit_Min_Point = uiNum_Vertices;
	
	while (!Convergence(lpcTest_Points, uiNum_Vertices , cThreshold, &cConvergence_Fault))
	{
		fprintf(stdout,"+");
		fflush(stdout);
//		fprintf(stdout,"F: %.1f %.1f %.1f %.1f %.1f %.1f %.1f\n",cConvergence_Fault.Get(0),cConvergence_Fault.Get(1),cConvergence_Fault.Get(2),cConvergence_Fault.Get(3),cConvergence_Fault.Get(4),cConvergence_Fault.Get(5),cConvergence_Fault.Get(6));

		// Find point with worst fit
		double	dFit_Max = 0.0;
		double	dFit_Near_Max = 0.0;
		double	dFit_Min = DBL_MAX;
		double	dFit_Variance = 0.0;
		double	dFit_Mean = 0.0;
		bool	bClose_Fit = true;
		uiFit_Max_Point = uiNum_Vertices;
		uiFit_Min_Point = uiNum_Vertices;
		for (unsigned int uiI = 0; uiI < uiNum_Vertices; uiI++)
		{
//			printf("%i : %.2e\n",uiI,lpdFit[uiI]);
			dFit_Variance += lpdFit[uiI] * lpdFit[uiI];
			dFit_Mean += lpdFit[uiI];
			if (lpdFit[uiI] > dFit_Max)
			{
				dFit_Max = lpdFit[uiI];
				uiFit_Max_Point = uiI;
			}
			if (lpdFit[uiI] < dFit_Min)
			{
				dFit_Min = lpdFit[uiI];
				uiFit_Min_Point = uiI;
			}
		}
		if (dFit_Min <= 0.5)
		{
			for (unsigned int uiI = 0; uiI < uiNum_Vertices; uiI++)
			{
				lpdFit[uiI] = lpdFit[uiFit_Min_Point];
				lpcTest_Points[uiI] = lpcTest_Points[uiFit_Min_Point];
			}
		}
		else
		{
			dFit_Variance /= uiNum_Vertices;
			dFit_Mean /= uiNum_Vertices;
			double dFit_Std_Dev = dFit_Variance - dFit_Mean * dFit_Mean;
//			for (unsigned int uiI = 0; uiI < uiNum_Vertices && bClose_Fit; uiI++)
//			{
//				bClose_Fit = (fabs(lpdFit[uiI] - dFit_Mean) < (2.0 * dFit_Std_Dev));
//			}
//			bClose_Fit |= (dFit_Std_Dev < 10.0);
			bClose_Fit &= (dFit_Std_Dev < 10.0);
			if (dFit_Near_Max == 0.0)
			{
				for (unsigned int uiI = 0; uiI < uiNum_Vertices; uiI++)
				{
					if (lpdFit[uiI] > dFit_Near_Max && uiI != uiFit_Max_Point)
						dFit_Near_Max = lpdFit[uiI];
				}
			}
	//		fprintf(stdout,"%i",uiFit_Max_Point);
	//		fprintf(stdout,"F: %.8e %.8e %.8e %.8e %.8e %.8e %.8e\n",dFit[0],dFit[1],dFit[2],dFit[3],dFit[4],dFit[5],dFit[6],dFit[7]);
	//		if (uiFit_Max_Point < uiNum_Vertices)
			{
				// Compute weighted centroid of remaining parameters
				for (unsigned int uiI = 0; uiI < cCentroid.Get_Size(); uiI++)
					cCentroid.Set(uiI,0.0);
				dFit_Sum = 0.0;
				for (unsigned int uiI = 0; uiI < uiNum_Vertices; uiI++)
				{
					if (uiI != uiFit_Max_Point)
					{
						XVECTOR cTemp = lpcTest_Points[uiI];
	//					lpcTest_Points[uiI].Print(NULL);
	//					cTemp.Print(NULL);
						if (lpdFit[uiI] > 1.0)
							cTemp *= lpdFit[uiI];
						cCentroid += cTemp;
	//					cCentroid.Print(NULL);
						if (lpdFit[uiI] > 1.0)
							dFit_Sum += lpdFit[uiI];
						else
							dFit_Sum += 1.0;
					}
				}
				cCentroid /= dFit_Sum;
	//			printf("Centroid\n");
	//			for (unsigned int uiI = 0; uiI < uiParameters; uiI++)
	//			{
	//				printf("%.1f\n",cCentroid.Get(uiI));
	//			}
				cTestOuter = lpcTest_Points[uiFit_Max_Point];
				cTestInner = cCentroid;
//				printf("\n");
//				cCentroid.Print();
				Generate_Synow_Spectra(i_cTarget,i_cOpacity_Map_A,i_cOpacity_Map_B,i_uiIon,cCentroid,cOutput);
				dTest_Fit = Fit(i_cTarget, cOutput, i_dMin_WL, i_dMax_WL, i_bChi2);
				if (bClose_Fit && !isnan(dTest_Fit) && !isinf(dTest_Fit))
				{
					for (unsigned int uiI = 0; uiI < uiNum_Vertices; uiI++)
					{
//						fprintf(stdout,"-%.0f\t%.2e\t%.0f\t%.0f\t%c\t%.1f\n",dTest_Fit,dFit_Min,dFit_Max,dFit_Near_Max,bClose_Fit ? 't' : 'f',dFit_Std_Dev);
						fprintf(stdout,"-");
						fflush(stdout);
						cDelta = cCentroid - lpcTest_Points[uiI];
						cDelta *= 0.5;
						lpcTest_Points[uiI] += cDelta;
						Generate_Synow_Spectra(i_cTarget,i_cOpacity_Map_A,i_cOpacity_Map_B,i_uiIon,lpcTest_Points[uiI],cOutput);
						lpdFit[uiI] = Fit(i_cTarget, cOutput, i_dMin_WL, i_dMax_WL, i_bChi2);
					}
				}
				else if (dTest_Fit > dFit_Near_Max)
				{
					cTestOuter = cCentroid;
					cTestInner = lpcTest_Points[uiFit_Min_Point];
					cTest = cTestInner;
					while (isnan(dTest_Fit) || isinf(dTest_Fit) || dTest_Fit > dFit_Near_Max)
					{
						//cCentroid.Print();
//						fprintf(stdout,"@%.0f\t%.2e\t%.0f\t%.0f\t%c\t%.1f\n",dTest_Fit,dFit_Min,dFit_Max,dFit_Near_Max,bClose_Fit ? 't' : 'f',dFit_Std_Dev);
						fprintf(stdout,"@");
						fflush(stdout);
						cDelta = cTestOuter - cTestInner;
						cDelta *= 0.5;
						cTest = cTestInner + cDelta;
//						cTest.Print();
						Generate_Synow_Spectra(i_cTarget,i_cOpacity_Map_A,i_cOpacity_Map_B,i_uiIon,cTest,cOutput);
						dTest_Fit = Fit(i_cTarget, cOutput, i_dMin_WL, i_dMax_WL, i_bChi2);
						cTestOuter = cTest;
/*						lpcTest_Points[uiFit_Max_Point] = cCentroid;
						lpdFit[uiFit_Max_Point] = dTest_Fit;
						for (unsigned int uiI = 0; uiI < cCentroid.Get_Size(); uiI++)
							cCentroid.Set(uiI,0.0);
						dFit_Sum = 0.0;
						for (unsigned int uiI = 0; uiI < uiNum_Vertices; uiI++)
						{
							XVECTOR cTemp = lpcTest_Points[uiI];
							if (lpdFit[uiI] > 1.0)
								cTemp *= lpdFit[uiI];
							cCentroid += cTemp;
							if (lpdFit[uiI] > 1.0)
								dFit_Sum += lpdFit[uiI];
							else
								dFit_Sum == 1.0;
						}
						cCentroid /= dFit_Sum;
						Generate_Synow_Spectra(i_cTarget,i_cOpacity_Map_A,i_cOpacity_Map_B,i_uiIon,cCentroid,cOutput);
						dTest_Fit = Fit(i_cTarget, cOutput, i_dMin_WL, i_dMax_WL, i_bChi2);
*/
					}
					lpcTest_Points[uiFit_Max_Point] = cTest;
					lpdFit[uiFit_Max_Point] = dTest_Fit;
				}
				else
				{
					cTest = lpcTest_Points[uiFit_Max_Point];
					double dTest_Fit = 0.0;
					while(isnan(dTest_Fit) || isinf(dTest_Fit) || (!bClose_Fit && dTest_Fit < dFit_Min))
					{
//						fprintf(stdout,"*%.0f\t%.2e\t%.0f\t%.0f\t%c\t%.1f\n",dTest_Fit,dFit_Min,dFit_Max,dFit_Near_Max,bClose_Fit ? 't' : 'f',dFit_Std_Dev);
						fprintf(stdout,"*");
						fflush(stdout);
						cDelta = cTestOuter - cTestInner;
						cDelta *= 0.5;
						cTest = cTestInner + cDelta;
//						cTest.Print();
						Generate_Synow_Spectra(i_cTarget,i_cOpacity_Map_A,i_cOpacity_Map_B,i_uiIon,cTest,cOutput);
						dTest_Fit = Fit(i_cTarget, cOutput, i_dMin_WL, i_dMax_WL, i_bChi2);
						cTestInner = cTest;
					}
					cTestOuter = cTest;
					cTestInner = cCentroid;
					while(isnan(dTest_Fit) || isinf(dTest_Fit) || dTest_Fit == 0.0 || dTest_Fit > dFit_Near_Max)
					{
//						fprintf(stdout,"%%%.0f\t%.2e\t%.0f\t%.0f\t%c\t%.1f\n",dTest_Fit,dFit_Min,dFit_Max,dFit_Near_Max,bClose_Fit ? 't' : 'f',dFit_Std_Dev);
						fprintf(stdout,"%%");
						fflush(stdout);
						cDelta = cTestOuter - cTestInner;
						cDelta *= 0.5;
						cTest = cTestInner + cDelta;
//						cTest.Print();
						Generate_Synow_Spectra(i_cTarget,i_cOpacity_Map_A,i_cOpacity_Map_B,i_uiIon,cTest,cOutput);
						dTest_Fit = Fit(i_cTarget, cOutput, i_dMin_WL, i_dMax_WL, i_bChi2);
						cTestOuter = cTest;
					}
					lpcTest_Points[uiFit_Max_Point] = cTest;
					lpdFit[uiFit_Max_Point] = dTest_Fit;
				}
			}
		}
		SavePointsCache(i_lpszFileSource,lpcTest_Points,uiNum_Vertices,uiParameters,lpdFit);
	}

//	printf("Convergence\n");
//	for (unsigned int uiI = 0; uiI < uiParameters; uiI++)
//	{
//		printf("%.1f\n",cConvergence_Fault.Get(uiI));
//	}
	for (unsigned int uiI = 0; uiI < cCentroid.Get_Size(); uiI++)
		cCentroid.Set(uiI,0.0);
	for (unsigned int uiI = 0; uiI < uiNum_Vertices; uiI++)
	{
		cCentroid += lpcTest_Points[uiI];
	}
	cCentroid /= (double)(uiNum_Vertices);

	int iT_ref = (int )(cCentroid.Get(0) + 0.5);
	if (iT_ref < 0)
		iT_ref = 0;
	if (iT_ref > (i_cOpacity_Map_A.GetNumColumns() - 2))
		iT_ref = i_cOpacity_Map_A.GetNumColumns() - 2;
	iT_ref++;

	o_dDay = i_cOpacity_Map_A.GetElement(iT_ref,0);
//	printf("%i %.2f\n",iT_ref,o_dDay);
	o_dPS_Vel = cCentroid.Get(1);
	o_dPS_Temp = cCentroid.Get(2);
	o_dPS_Ion_Temp = cCentroid.Get(3);
	o_dPS_Log_Tau = cCentroid.Get(4);
	o_dHVF_Ion_Temp = cCentroid.Get(5);
	o_dHVF_Log_Tau = cCentroid.Get(6);

	fprintf(stdout,"X");
	fflush(stdout);
	Generate_Synow_Spectra(i_cTarget,i_cOpacity_Map_A,i_cOpacity_Map_B,i_uiIon,cCentroid,cOutput);
	o_cOutput = cOutput; // not completely sure why this has to be done instead of passing o_cOutput as a parameter to Generate_Synow_Spectra, but if I do the latter it returns with flux set to zero...
//	system("rm spectrafit.cache");
	return Fit(i_cTarget, o_cOutput, i_dMin_WL, i_dMax_WL, i_bChi2);
}