int XLALSQTPNAllocateCoherentGW(CoherentGW *wave, UINT4 length) {

	if (!wave) {
		XLAL_ERROR(XLAL_EFAULT);
	}
	if (length <= 0) {
		XLAL_ERROR(XLAL_EBADLEN);
	}
	if (wave->a || wave->f || wave->phi || wave->shift) {
		XLAL_ERROR(XLAL_EFAULT);
	}
	wave->a = (REAL4TimeVectorSeries *)LALMalloc(sizeof(REAL4TimeVectorSeries));
	wave->f = (REAL4TimeSeries *)LALMalloc(sizeof(REAL4TimeSeries));
	wave->phi = (REAL8TimeSeries *)LALMalloc(sizeof(REAL8TimeSeries));
	wave->shift = (REAL4TimeSeries *)LALMalloc(sizeof(REAL4TimeSeries));
	if (!(wave->a && wave->f && wave->phi && wave->shift)) {
		XLALSQTPNDestroyCoherentGW(wave);
		XLAL_ERROR(XLAL_ENOMEM);
	}
	xlalErrno = 0;
	wave->a->data = XLALCreateREAL4VectorSequence(length, 2);
	wave->f->data = XLALCreateREAL4Vector(length);
	wave->phi->data = XLALCreateREAL8Vector(length);
	wave->shift->data = XLALCreateREAL4Vector(length);
	if (!(wave->a->data && wave->f->data && wave->phi->data && wave->shift->data)) {
		XLALSQTPNDestroyCoherentGW(wave);
		XLAL_ERROR(XLAL_ENOMEM);
	}
	return XLAL_SUCCESS;
}
int XLALSQTPNWaveformForInjection(CoherentGW *waveform, 
		InspiralTemplate *params, PPNParamStruc *ppnParams) {

	// Check the relevant pointers
	if( !waveform || !params || waveform->a || waveform->f
			|| waveform->phi || waveform->shift )
		XLAL_ERROR(XLAL_EFAULT);

	// variable declaration and initialization
	UINT4 i;
	InspiralInit paramsInit;

	// Compute some parameters
	XLALInspiralInit(params, &paramsInit);
	if (xlalErrno)
		XLAL_ERROR(XLAL_EFUNC);
	if (paramsInit.nbins == 0) {
		XLALPrintWarning("Warning! Waveform of zero length requested in %s. Returning empty waveform.\n ", __func__);
		return XLAL_SUCCESS;
	}

	// Allocate the waveform structures.
	xlalErrno = 0;
	XLALSQTPNAllocateCoherentGW(waveform, paramsInit.nbins);

	LALSQTPNWave wave;
	wave.h = NULL;
	wave.hp = wave.hc = NULL;
	wave.waveform = waveform;
	LALSQTPNWaveformParams wave_Params;

	// filling the parameters
	XLALSQTPNFillParams(&wave_Params, params);
	if (xlalErrno)
		XLAL_ERROR(XLAL_EFUNC);

	// calling the engine function
	if(XLALSQTPNGenerator(&wave, &wave_Params)) {
		XLALSQTPNDestroyCoherentGW(waveform);
		XLAL_ERROR(XLAL_EFUNC);
	}
	params->fFinal = wave_Params.finalFreq;
	for (i = 0; i < wave.length; i++) {
		if (waveform->phi->data->data[i] != 0.) {
			break;
		}
		if (i == wave.length - 1) {
			XLALSQTPNDestroyCoherentGW(waveform);
			XLAL_ERROR(XLAL_EFUNC);
		}
	}

	{
		if (waveform->a != NULL) {
			waveform->f->data->length = waveform->phi->data->length 				= waveform->shift->data->length = wave.length;
			waveform->a->data->length = 2 * wave.length;
			for (i = 0; i < wave.length; i++) {
				// (PPNParamStruct)ppnParams->phi === (InspiralTemplate)params->startPhase === (SimInspiralTable)injparams/this_event->coa_phase it is set to 0 in LALSQTPNWaveformTest.c at line 83.
				waveform->phi->data->data[i] 
					= waveform->phi->data->data[i] 
					- waveform->phi->data->data[wave.length-1] 
					+ ppnParams->phi;
			}
			waveform->a->deltaT = waveform->f->deltaT 
					= waveform->phi->deltaT
					= waveform->shift->deltaT 
					= 1. / params->tSampling;

			waveform->a->sampleUnits = lalStrainUnit;
			waveform->f->sampleUnits = lalHertzUnit;
			waveform->phi->sampleUnits = lalDimensionlessUnit;
			waveform->shift->sampleUnits = lalDimensionlessUnit;

			waveform->position = ppnParams->position;
			waveform->psi = ppnParams->psi;

			snprintf(waveform->a->name, LALNameLength,
					"STPN inspiral amplitudes");
			snprintf(waveform->f->name, LALNameLength,
					"STPN inspiral frequency");
			snprintf(waveform->phi->name, LALNameLength, 
					"STPN inspiral phase");
			snprintf(waveform->shift->name, LALNameLength,
					"STPN inspiral polshift");
		}
		// --- fill some output ---
		ppnParams->tc = (REAL8) (wave.length - 1) / params->tSampling;
		ppnParams->length = wave.length;
		ppnParams->dfdt 
			= ((REAL4) (waveform->f->data->data[wave.length - 1]
			- waveform->f->data->data[wave.length - 2])) 
			* ppnParams->deltaT;
		ppnParams->fStop = params->fFinal;
		ppnParams->termCode = GENERATEPPNINSPIRALH_EFSTOP;
		ppnParams->termDescription = GENERATEPPNINSPIRALH_MSGEFSTOP;

		ppnParams->fStart = ppnParams->fStartIn;
	} // end phase condition

	return XLAL_SUCCESS;
}
/** The main program.
 */
int main(int argc, char *argv[]) {

	// variable declaration and initialization
	static LALStatus mystatus;
	CoherentGW thewaveform;
	SimInspiralTable injParams;
	PPNParamStruc ppnParams;
	//const char *filename;
	FILE *outputfile;
	INT4 i, length;
	REAL8 dt;
	char PNString[50];
	char filename[50];

	if (argc != 16) {
		printf(
				"                         1  2  3   4   5   6   7   8   9    10	     11	     12       13 14      15\n");
		printf(
				"Correct parameter order: m1 m2 S1x S1y S1z S2x S2y S2z incl f_lower f_final distance dt PNorder SpinInter\n");
		return (1);
	}
	
	sprintf(PNString, "SpinQuadTaylor%s%s", argv[14], argv[15]);
	sprintf(filename, "%s%s.out", argv[14], argv[15]);
	//filename = argv[15];
	memset(&mystatus, 0, sizeof(LALStatus));
	memset(&thewaveform, 0, sizeof(CoherentGW));
	memset(&injParams, 0, sizeof(SimInspiralTable));
	memset(&ppnParams, 0, sizeof(PPNParamStruc));

	//	setting the parameters
	injParams.mass1 = atof(argv[1]);
	injParams.mass2 = atof(argv[2]);
	injParams.spin1x = atof(argv[3]);
	injParams.spin1y = atof(argv[4]);
	injParams.spin1z = atof(argv[5]);
	injParams.spin2x = atof(argv[6]);
	injParams.spin2y = atof(argv[7]);
	injParams.spin2z = atof(argv[8]);
	injParams.qmParameter1 = 1.;//atof(argv[9]);
	injParams.qmParameter2 = 1.;//atof(argv[10]);
	injParams.inclination = atof(argv[9]);
	injParams.f_lower = atof(argv[10]);
	injParams.f_final = atof(argv[11]);
	injParams.distance = atof(argv[12]);
	ppnParams.deltaT = atof(argv[13]);
	injParams.polarization = 0;
	LALSnprintf(injParams.waveform, LIGOMETA_WAVEFORM_MAX * sizeof(CHAR),
			PNString);

	//interface(&mystatus, &thewaveform, &injParams, &ppnParams);
	LALGenerateInspiral(&mystatus, &thewaveform, &injParams, &ppnParams);
	if (mystatus.statusCode) {
		fprintf( stderr, "LALSQTPNWaveformTest: error generating waveform\n" );
		return mystatus.statusCode;
	}
	// and finally save in a file
	outputfile = fopen(filename, "w");

	length = thewaveform.f->data->length;
	dt      = thewaveform.phi->deltaT;
    REAL8       a1, a2, phi, shift;
    for(i = 0; i < length; i++) {
        a1  = thewaveform.a->data->data[2*i];
        a2  = thewaveform.a->data->data[2*i+1];
        phi     = thewaveform.phi->data->data[i] - thewaveform.phi->data->data[0];
        shift   = thewaveform.shift->data->data[i];

        fprintf(outputfile,"% 10.7e\t% 10.7e\t% 10.7e\n",
            i*dt,
            a1*cos(shift)*cos(phi) - a2*sin(shift)*sin(phi),
            a1*sin(shift)*cos(phi) + a2*cos(shift)*sin(phi));
    }
	fclose(outputfile);
	XLALSQTPNDestroyCoherentGW(&thewaveform);
	puts("Done.");
	LALCheckMemoryLeaks();
	return mystatus.statusCode;
}