The Origin Forum
File Exchange
Try Origin for Free
The Origin Forum
Home | Profile | Register | Active Topics | Members | Search | FAQ | Send File to Tech support
Username:
Password:
Save Password
Forgot your Password? | Admin Options

 All Forums
 Origin Forum
 Origin Forum
 Access to worksheet from external DLL fit function
 New Topic  Reply to Topic
 Printer Friendly
Author Previous Topic Topic Next Topic Lock Topic Edit Topic Delete Topic New Topic Reply to Topic

Stefan.E.S

Germany
11 Posts

Posted - 04/23/2010 :  09:11:19 AM  Show Profile  Edit Topic  Reply with Quote  View user's IP address  Delete Topic
Origin Ver. and Service Release : 8.1G SR2
Operating System: WinXP

In a fit function I need to access data which are contained in an Origin worksheet. The fit function is programmed as using Microsoft Visual C++.

Can I use e.g. lParam1 or LParam2 from the FIT_PARA_LIST below for access to an origin worksheet?


#define FIT_PARA_LIST  short cntrl, DWORD lpProc, short nParam, DWORD lParam1, DWORD lParam2, LPDOUBLE p, LPDOUBLE c, LPDOUBLE x, LPDOUBLE y, LPDOUBLE dy


Furthermore, I would like to use the number (index) of the current x-axis data point in my fit function.

How can this be retrieved in an external DLL fit function?

Stefan.E.S

Germany
11 Posts

Posted - 04/29/2010 :  04:03:30 AM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
I forgot to mention that access to origin worksheets from external DLL fitting functions was possible with Origin 7.5. I just wonder how this functionality can be used in Origin 8.1. Below a copy of a working orgin 7.5 example. A response from OriginLab would be appreaciated.

Thanks,

Stefan



#include <windows.h>

/* The following entry function
 * related to Windows
 */
#ifndef _WIN32

int FAR PASCAL LibMain(hModule, wDataSeg, cbHeapSize, lpszCmdLine)
HANDLE	hModule;
WORD    wDataSeg;
WORD    cbHeapSize;
LPSTR   lpszCmdLine;
{
    return 1;/* Nothing is done, but it is necessary */
}

//	ANU v4.134 9/30/96 32_BIT_COMPATIBLE
#else  //_WIN32

BOOL WINAPI DllMain (HANDLE hModule, DWORD fdwReason, LPVOID lpReserved)
{
	 
   // The return value is only used for DLL_PROCESS_ATTACH; all other
   //   conditions are ignored.  
	return TRUE;   // successful DLL_PROCESS_ATTACH
}

#endif
///end 32_BIT_COMPATIBLE


/* Your DLL code starts here */

#include    <math.h>
#include    <stdio.h>
#include    "orgdll.h"

///Function names have to be upper case so that origin can
//recognize the functions.




int FAR  PASCAL THEOFIT(
	HWND			hWnd,	/* Origin's main window */
	double FAR *	lpValue,/* input (x) ,output (y)*/
	short			nParam, /* number of parameters */
	double FAR *	lpParam,/* parameter array */
	LPCALLBK lpfn)
{

/*  Fitting of a weighted sum of theoretical spectra to an experimental spectrum.
    The theoretical spectra are assumed to be contained in a workshhet named "Theory"
	and to have a common, equidistant energy axis that is col. no. 1 in the worksheet.
	The spectra are assumed to be in the subsequent columns. Column names can be arbitrary.
	The number of parameters to be given in the fdf-file is 3 + number of spectra) */


	/* Fit parameters are
	 *     lpParam[0]				   : overall scale factor
	 *     lpParam[1..2]               : linear background (subtracted)
	 *     lpParam[3..nspec+3]		   : individual scale factor for each spectrum
	 *     lpParam[nspec+4..2*nspec+3] : energy shift for each spectrum
	 * nspec, npts and theory[npts][nspec+1] are defined in Theospec.h
	 * with the theoretical energy scale stored in theory[npts][0] 
	 */
    
	double	x = *lpValue;
    if (x<=0) {*lpValue=0;return (0);} 
	/* lpValue point to a temperary location
	 * that contains the X value on input
	 */

    int nspec = (nParam-3)/2;
	
    char TheoryWksName[80], colname[80], cstr[80];

    typedef char SpecName[80];
    
    SpecName Theory_E, *Theory_Spectrum = new SpecName[nspec];	 

	strcpy(TheoryWksName,"Theory");

	// get name of 1st column in theory worksheet (energy)
    lpfn(hWnd,WCB_EXECUTE,"%A=Theory!WKS.COL1.NAME$",0L);
	lpfn(hWnd,WCB_GET_STRING,(LPSTR)colname,0);
	strcpy(Theory_E,TheoryWksName);
	strcat(Theory_E,"_");
	strcat(Theory_E,colname);
    
	int n;

    for (n=1;n<=nspec;n++)
	{
		// get name of n+1st column in theory worksheet (spectra)
		sprintf(cstr,"%%A=Theory!WKS.COL%d.NAME$",n+1);
		lpfn(hWnd,WCB_EXECUTE,cstr,0L);
		lpfn(hWnd,WCB_GET_STRING,(LPSTR)colname,0);
		strcpy(Theory_Spectrum[n-1],TheoryWksName);
		strcat(Theory_Spectrum[n-1],"_");
		strcat(Theory_Spectrum[n-1],colname);
		// output to script window for debugging purposes
		// sprintf(cstr,"type -a $(%d) %s",n,Theory_Spectrum[n-1]);
		// lpfn(hWnd,WCB_EXECUTE,(LPSTR)cstr,0L);
	}

	// variables needed for reading data from worksheets
	long range[4];
	DWORD data_id;
	DATAELEMENT data;

	data.index = 0;
	data_id = lpfn(hWnd, WCB_DATA_GET_ID, (LPSTR)Theory_E, (LPSTR)range);
	lpfn(hWnd, WCB_DATA_GET_VALUE, (LPSTR)data_id, (LPSTR)(&data));
	double x0 = data.value;
    long int npts = range[1];

	data.index = 1;
	data_id = lpfn(hWnd, WCB_DATA_GET_ID, (LPSTR)Theory_E, (LPSTR)range);
	lpfn(hWnd, WCB_DATA_GET_VALUE, (LPSTR)data_id, (LPSTR)(&data));
	double x1 = data.value;

	double dx = x1-x0;
	double y=0;
   
    int i;
	for (int j=0;j<nspec;j++)
	{
		double eshift = lpParam[3+nspec+j];
    	i = int((x-x0-eshift)/dx);

/*
//      in case of non equidistant x-values use the following instructions
		for (i=npts-1;i>=0;i--)
		    {
			data.index = i;
			data_id = lpfn(hWnd, WCB_DATA_GET_ID, (LPSTR)Theory_E, (LPSTR)range);
			lpfn(hWnd, WCB_DATA_GET_VALUE, (LPSTR)data_id, (LPSTR)(&data));
			double xi = data.value+eshift;
			if (x<xi) break;
		}
*/
		if ((i>0) && (i<npts-2))
		{

			data.index = i;
			data_id = lpfn(hWnd, WCB_DATA_GET_ID, (LPSTR)Theory_E, (LPSTR)range);
			lpfn(hWnd, WCB_DATA_GET_VALUE, (LPSTR)data_id, (LPSTR)(&data));
			double x1 = data.value+eshift;
			data.index = i;
			data_id = lpfn(hWnd, WCB_DATA_GET_ID, (LPSTR)Theory_Spectrum[j], (LPSTR)range);
			lpfn(hWnd, WCB_DATA_GET_VALUE, (LPSTR)data_id, (LPSTR)(&data));
			double y1 = data.value;
			data.index = i+1;
			data_id = lpfn(hWnd, WCB_DATA_GET_ID, (LPSTR)Theory_Spectrum[j], (LPSTR)range);
			lpfn(hWnd, WCB_DATA_GET_VALUE, (LPSTR)data_id, (LPSTR)(&data));
			double y2 = data.value;
    		y += lpParam[j+3]*(y1 + (x-x1)*(y2-y1)/dx);
		}
	}

  y *= lpParam[0]; // overall scale factor
  y -= lpParam[1]+x*lpParam[2]; //  subtract background

  *lpValue = y; // result of the function is stored back to lpValue 
 
  delete[] Theory_Spectrum;

  return(0);
 	/* You must return zero if there is no error
     * otherwise you can return any number other than
	 * zero to signal an error
	 */
}






StSch
Go to Top of Page

Stefan.E.S

Germany
11 Posts

Posted - 04/29/2010 :  04:45:18 AM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
I just found out that I simply had to recompile the DLL using the Origin 8.1 header file "OriginLab\Orgin81\ATI\include\ORGDLL.H" instead of "FitFuncDef.H". Now the fitting works.

I suggest to supply documentation for fitting with fit functions from an external DLL using ORGDLL.H. Currently there is only documentation for "FitFuncDef.h".

Below I attach the fdf-file that I use for running the example from my previous post




[General Information]
Function Name = Theofit4
Brief Description = linear combination of theoretical spectra
Function Source = Theofit.1
Function Type = External DLL
Function Form = Expression
Number Of Parameters = 11
Number Of Independent Variables = 1
Number Of Dependent Variables = 1
Analytical Derivatives for User-Defined = 0
FunctionPrev = Theofit4


[Fitting Parameters]
Naming Method = User-Defined
Names = yscale,a0,a1,c1S,c3P0,c3P1,c3P2,es1S,es3P0,es3P1,es3P2
Meanings = xxx,xxx,xxx,xxx
Initial Values = 1.0(F),0.0(F),0.0(F),0.25(V),0.25(V),0.25(V),0.25(V),0(F),0(F),0(F),0(F)
Lower Bounds = 0.0,--,--,0.0,0.0,0.0,0.0,--,--,--,--
Upper Bounds = --,--,--,1.0,1.0,1.0,1.0,--,--,--,--
Number Of Significant Digits = 8,8,8,8,8,8,8,8,8,8,8


[Formula]
formula goes here;


[Constraints]
c1s+c3P0+c3P1+c3P2=1;
es3P1=es3P0;
es3P2=es3P0;


[Constants]


[Parameters Initialization]


[Initializations]


[After Fitting]


[Independent Variables]
x = 


[Dependent Variables]
y = 


[Controls]
General Linear Constraints = 0
Initialization Scripts = 1
Scripts After Fitting = 0
Number Of Duplicates = N/A
Duplicate Offset = N/A
Duplicate Unit = N/A
Generate Curves After Fitting = 1
Curve Point Spacing = Same X as Fitting Data
Generate Peaks After Fitting = 0
Generate Peaks During Fitting = 0
Generate Peaks with Baseline = 0
Paste Parameters to Plot After Fitting = 1
Paste Parameters to Notes Window After Fitting = 1
Generate Residuals After Fitting = 0
Keep Parameters = 1
Enable Parameters Initialization = 0
Compile On Param Change Script = 0


[Compile Function]
Compile = 0
Compile Parameters Initialization = 0
OnParamChangeScriptsEnabled = N/A


[Origin C Function Header]


[Origin C Parameter Initialization Header]


[References]






StSch
Go to Top of Page
  Previous Topic Topic Next Topic Lock Topic Edit Topic Delete Topic New Topic Reply to Topic
 New Topic  Reply to Topic
 Printer Friendly
Jump To:
The Origin Forum © 2020 Originlab Corporation Go To Top Of Page
Snitz Forums 2000