- 1. perClass C/C++ API
- 2. Library version information
- 2.1. sd_GetVersion
- 3. Initialization and releasing the library
- 3.1. sd_InitKernel
- 3.2. sd_InitKernelLicString
- 3.3. sd_ReleaseKernel
- 4. Status and error reporting
- 4.1. sd_GetLicenseInfo
- 4.2. sd_GetErrorMsg
- 4.3. sd_GetErrorCode
- 4.4. perClass runtime error messages
- 4.5. #define SD_OK 0
- 4.6. #define SD_ERROR -1
- 4.7. #define SD_YES 1
- 4.8. #define SD_NO 0
- 5. Loading and releasing pipelines
- 5.1. sd_LoadPipeline
- 5.2. sd_LoadPipelineFromBuffer
- 5.3. sd_ReleasePipeline
- 5.4. sd_GetPipelineCount
- 6. Operations on a specific loaded pipeline
- 6.1. sd_GetPipelineName
- 6.2. sd_GetInputFc
- 6.3. sd_GetOutputFc
- 6.4. sd_GetDecCount
- 6.5. sd_GetDecName
- 7. Attaching and detaching application memory to/from the pipeline
- 7.1. sd_AttachMemToInput - Attach memory chunk allocated by the application to the pipeline input
- 7.2. sd_AttachMemToOutput - Attach memory chunk allocated by the application to the pipeline input
- 7.3. sd_BufAttachToInput - Attach buffer object to the pipeline input (see below for data buffer object)
- 7.4. sd_BufAttachToOutput - Attach buffer object to the pipeline output (see below for data buffer object)
- 7.5. sd_DetachInput - Detach memory attached to the pipeline input
- 7.6. sd_DetachOutput - Detach memory attached to the pipeline output
- 8. Pipeline execution
- 8.1. sd_IsReadyToExecute
- 8.2. sd_Execute
- 8.3. sd_SetOp Set classifier to a specific operating point
- 8.4. sd_GetOp Get current operating point of a classifier
- 8.5. sd_GetOpCount Retrieve number of classifier operating points
- 8.6. sd_GetClassifierCount Retrieve number of classifiers in a pipeline
- 9. Data buffers
- 9.1. sd_BufNew Allocate memory buffer
- 9.2. sd_BufNewReferringTo - Create buffer refering to existing application memory chunk
- 9.3. sd_BufLoadFromCSVFile - Allocate a buffer and fill it with data from a comma-separated file
- 9.4. sd_BufFree - Free a buffer
- 9.5. sd_BufGetSc - Return the number of samples in a buffer
- 9.6. sd_BufSetSc - Set the number of actual samples in the allocated buffer
- 9.7. sd_BufGetFc - Return the number of features in a buffer
- 10. Getting/Setting values in a buffer
- 10.1. sd_BufGetValueDouble
- 10.2. sd_BufGetValueSingle
- 10.3. sd_BufGetValueInt
- 10.4. sd_BufSetValueDouble
- 10.5. sd_BufSetValueSingle
- 10.6. sd_BufSetValueInt
- 11. Cross-platform precision timers
FREFLOCAL:
1. perClass C/C++ API ↩
perClass software is composed of two parts -- the Matlab-based perClass Toolbox for design of classifiers and perClass Runtime for execution of classifiers in custom applications.
This document describes C/C++ application programing interface (API) of the perClass Runtime.
2. Library version information ↩
2.1. sd_GetVersion ↩
const char* API sd_GetVersion();
Input
none
Output
- pointer to string describing perClass Runtime version. The format is
VERSION (RELDATE)
e.g.4.3 (20-May-2014)
3. Initialization and releasing the library ↩
3.1. sd_InitKernel ↩
prkernel* sd_InitKernel(char* lic_path)
Input
lic_path
string path to the license file. Use NULL for searching the directory where the library binary is located
Output
- pointer to the
prkernel
structure or NULL when library initialization failed. Usesd_GetErrorMsg
to obtain detailed description of the problem.
Description
sd_InitKernel
is initializes the library and provides pk
opaque pointer
that is used for most API calls.
3.2. sd_InitKernelLicString ↩
prkernel* sd_InitKernelLicString(char* lic);
Input
lic
pointer to a license string buffer. The license string must be enclosed in<
>
brackets (<LICENSE ...>
).
Output
- pointer to the
prkernel
structure or NULL when library initialization failed. Usesd_GetErrorMsg
to obtain detailed description of the problem.
3.3. sd_ReleaseKernel ↩
void sd_ReleaseKernel(prkernel* pk);
Input
pk
pointer to the prkernel structure
Description
Call sd_ReleaseKernel
to release all memory allocated by the perClass runtime (all loaded pipelines and buffers allocated through library interface calls). The user is responsible for freeing all memory buffers allocated outside perClass runtime.
4. Status and error reporting ↩
4.1. sd_GetLicenseInfo ↩
const char* API sd_GetLicenseInfo(prkernel* pk);
Input
pk
pointer to the prkernel structure
Output
- string with detailed description of the runtime licenses present
Description
sd_GetLicenseInfo
provides license details read at the time of library
initialization with one of sd_InitKernel* routines. Two types of runtime
licenses are supported, namely runtime.demo and runtime. In case, the
license error is reported, this function does not provide any details but
error message is given via sd_GetErrorMsg
function.
Example output of sd_GetLicenseInfo
:
machine: hostid="00a3ffa0" ip=192.168.2.124
license: product="runtime.demo" present=1 exp=30-sep-2017 exp_days=143 issued=9-may-2017 hostid="ANY"
license: product="runtime" present=1 exp=11-may-2017 exp_days=1 issued=8-may-2017 options="CP,imaging" customer="" contract="" hostid="00a3ffa0"
The intention is that the returned string is machine-parsable and can provide custom application with useful details such as presence/absence of a license or days to expiration.
Each line starts with type string (e.g. machine or license). The machine
type defines hostid and IP address of the current machine. The license
type lists presence or absence of a given license and additional details
ina format FIELD = VALUE
. Values may be enclosed in double-quotes and may
contain spaces.
4.2. sd_GetErrorMsg ↩
const char* sd_GetErrorMsg(prkernel* pk);
Input
pk
pointer to the prkernel structure
Output
- string with detailed description of the last error
Description
sd_GetErrorMsg
returns copyritght message and version number after the runtime initialization call using either sd_InitKernel
or sd_InitKernelLicString
.
4.3. sd_GetErrorCode ↩
int sd_GetErrorCode(prkernel* pk);
Input
pk
pointer to the prkernel structure
Output
- code of the last error reported by perClass runtime
Description The error codes and messages are listed here
4.4. perClass runtime error messages ↩
- error code: error message
-17
:sd_LoadPipeline
: Memory cannot be allocated-18
:sd_LoadPipeline
: Memory cannot be allocated-100
:sd_LoadPipeline
: Pipeline requires runtime of higher version-101
: perClass license error: Error initializing license system-102
: perClass license error: Error checking out license-103
: perClass license error: Wrong lincense format (please contact support@perclass.com)-104
: perClass license error: Unsupported license type (wrongly generated license)-106
:sd_LoadPipeline
: Error opening pipeline file (file does not exist or is not readable)-107
:sd_LoadPipeline
: Unknown pipeline format-108
:sd_LoadPipeline
: Unknown pipeline file format-109
:sd_LoadPipeline
: Loading algorithm failed, data mismatch.-110
:sd_InitKernel
: Error checking out runtime demo license-111
:sd_LoadPipeline
: No license to load this pipeline type-201
:sd_GetInputFc
: Pipeline not loaded.-202
:sd_GetOutputFc
: Pipeline not loaded.-203
:sd_AttachMemToInput
: Pipeline not loaded.-204
:sd_AttachMemToInput
: NULL pointer passed.-205
:sd_AttachMemToInput
: Currently attached pipeline must be detached first. Freeing it is application responsibility.-206
:sd_AttachMemToInput
: Wrong feature size.-207
:sd_AttachMemToInput
: Internal error.-208
:sd_BufAttachToInput
: Pipeline not loaded.-209
:sd_BufAttachToInput
: NULL pointer passed.-210
:sd_BufAttachToInput
: Wrong feature size.-211
:sd_AttachMemToOutput
: Pipeline not loaded.-212
:sd_AttachMemToOutput
: NULL pointer passed.-213
:sd_AttachMemToOutput
: Currently attached pipeline must be detached first. Freeing it is application responsibility.-214
:sd_AttachMemToOutput
: Wrong feature size.-215
:sd_AttachMemToOutput
: Internal error.-216
:sd_BufAttachToOutput
: Pipeline not loaded.-217
:sd_BufAttachToOutput
: NULL pointer passed.-218
:sd_BufAttachToOutput
: Wrong feature size.-219
:sd_IsReadyToExecute
: Pipeline not loaded.-220
:sd_IsReadyToExecute
: Internal error. Missing input buffer.-221
:sd_IsReadyToExecute
: Pipeline input is not connected to an application memory buffer.-222
:sd_IsReadyToExecute
: Internal error. Missing output buffer.-223
:sd_IsReadyToExecute
: Pipeline output is not connected to an application memory buffer.-225
:sd_LoadPipeline
: Unsupported license type.-226
:sd_LoadPipeline
: Cannot open pipeline file.-301
:sd_BufLoadFromCSVFile
: Error reading data.-302
:sd_BufSetSc
: Sample count out of bounds.-303
:sd_BufGetValue
: Sample or feature index out of bounds.-304
:sd_BufSetValue
: Sample or feature index out of bounds.-310
:sd_BufNew
: Incorrect buffer data type.-311
:sd_BufNewReferringTo
: NULL pointer passed.-312
:sd_BufNewReferringTo
: Incorrect buffer data type.
4.5. #define SD_OK 0
4.6. #define SD_ERROR -1
4.7. #define SD_YES 1
4.8. #define SD_NO 0
5. Loading and releasing pipelines ↩
5.1. sd_LoadPipeline ↩
int sd_LoadPipeline(prkernel* pk, char* filename);
Input
pk
pointer to the prkernel structurefilename
string buffer with name of the pipeline binary file saved using sdexport command from Matlab
Output
- zero-based pipeline index
pind
if successful orSD_ERROR
Description
Multiple pipelines may be loaded into one perClass runtime session (using a
single pk
structure). The user may execute, for example, a feature
extractor in one part of the application and several different classifiers
in the other. The pipelines may be loaded once and then used multiple
times. All pipeline specific functions take both pk
pointer structure and
the pipeline index pind
as the first two input arguments.
To remove a pipline, use sd_ReleasePipeline
function.
5.2. sd_LoadPipelineFromBuffer ↩
int sd_LoadPipelineFromBuffer(prkernel* pk, const char* buf);
Input
pk
pointer to the prkernel structurebuf
buffer with pipeline data
Output
- zero-based pipeline index
pind
if successful orSD_ERROR
Description
Pipeline may be loaded from in-memory buffer. In this way, pipelines may be
stored in application resources or sent over network. The sdexport command
of perClass Toolbox provides header
option that exports a pipeline
directly as a C header file that can be statically linked to the
application. The sd_LoadPipelineFromBuffer
is then used on the ppl_buf
variable.
Example of a pipeline generated with sdexport(p,'out.h','header')
command:
/* perClass pipeline stored in a C header file
name: Gaussian model+Decision
size: [2 1]
output: decisions
minimum perClass runtime version: 4.0 (11-jul-2013)
generated using sdexport on: [19-May-2014 13:56:52] */
char ppl_buf[]=\
"bXYGAOQJAADwCQAAiYl2sF9EEoCYBhvvFsiTkk9N4OzC82M09sTFYZA6TPWImabGb/VdY2J0JKha" \
"R3+iO3Gi+dJAnxHRPgLNCTRqUonhrMQaJDTKfUZxRUhjMmdmamUjrow+jTs+X2ypJ80sRNdGhAfC" \
...
5.3. sd_ReleasePipeline ↩
void sd_ReleasePipeline(prkernel* pk, int pind);
Input
pk
pointer to the prkernel structurepind
pipeline index
Output
none
Description
sd_ReleasePipeline
removes a pipeline from perClass Runtime and releases
all memory allocated by perClass. Subsequent calls to sd_LoadPipeline
or
sd_LoadPipelineFromBuffer
may re-use the pind
for newly loaded
pipeline.
At the application exit, it is sufficient to call sd_ReleaseKernel
as it
calls sd_ReleasePipeline
for each loaded pipeline.
5.4. sd_GetPipelineCount ↩
int sd_GetPipelineCount(prkernel* pk);
Input
pk
pointer to the prkernel structure
Output
- number of pipelines loaded in the perClass runtime kernel
pk
.
6. Operations on a specific loaded pipeline ↩
6.1. sd_GetPipelineName ↩
char* sd_GetPipelineName(prkernel* pk,int pind);
Input
pk
pointer to the prkernel structurepind
pipeline index
Output
- Name of pipeline
pind
, set using thesetname
method of sdppl object in perClass Toolbox
Description
Each pipeline carries a string human-readable name. Its purpose is to make
it easy for application developer to distinguish different classifiers at
runtime. Use setname
method in perClass Toolbox to provide descriptive
pipeline names to your classifiers (e.g. linking to research diary or log
so you may always see how exactly was certain classifier trained).
6.2. sd_GetInputFc ↩
int sd_GetInputFc(prkernel* pk,int pind);
Input
pk
pointer to the prkernel structurepind
pipeline index
Output
- input feature count for a given pipeline
6.3. sd_GetOutputFc ↩
int sd_GetOutputFc(prkernel* pk,int pind);
Input
pk
pointer to the prkernel structurepind
pipeline index
Output
- output feature count for a given pipeline
6.4. sd_GetDecCount ↩
int sd_GetDecCount(prkernel* pk,int pind);
Input
pk
pointer to the prkernel structurepind
pipeline index
Output
- number of pipeline decisions (zero for pipelines, such as feature extractors, returning general data)
6.5. sd_GetDecName ↩
const char* sd_GetDecName(prkernel* pk,int pind,int dcode);
Input
pk
pointer to the prkernel structurepind
pipeline indexdcode
decision code
Output
- pointer to the decision name given the decision code
Description
sd_GetDecName
converts decision code returned by a classifier to a string
decision name. The decision codes are identical to one-based indices in the
pipeline list p.list
in perClass Toolbox.
7. Attaching and detaching application memory to/from the pipeline ↩
7.1. sd_AttachMemToInput - Attach memory chunk allocated by the application to the pipeline input ↩
int sd_AttachMemToInput(prkernel* pk,int pind,double* ptr,int sc,int fc);
Input
pk
pointer to the prkernel structurepind
pipeline indexptr
pointer to externally allocated data buffersc
sample countfc
feature count
Output
- status code (
SD_OK
orSD_ERROR
)
Description
sd_AttachMemToInput
connects the externally-allocated buffer with input
data to the pipeline input. perClass assumes sample-per-sample memory
ordering where all features of the same sample are stored together in
memory. In other words, offset to next feature is 1 and to next sample is
fc.
7.2. sd_AttachMemToOutput - Attach memory chunk allocated by the application to the pipeline input ↩
int sd_AttachMemToOutput(prkernel* pk,int pind,double* ptr,int sc,int fc);
Input
pk
pointer to the prkernel structurepind
pipeline indexptr
pointer to externally allocated data buffersc
sample countfc
feature count
Output
- status code (
SD_OK
orSD_ERROR
)
Description
sd_AttachMemToOutput
connects the externally-allocated results buffer to the pipeline output.
The function assumes that memory represents a set of data samples stored in
such a way that the offset to the next feature is 1 and offset to the next
sample is fc
(the number of features).
7.3. sd_BufAttachToInput - Attach buffer object to the pipeline input (see below for data buffer object) ↩
int sd_BufAttachToInput(prkernel* pk,int pind,prbuf* pb);
Input
pk
pointer to the prkernel structurepind
pipeline indexpb
pointer to theprbuf
object
Output
- status code (
SD_OK
orSD_ERROR
)
Description
sd_BufAttachToInput
connects the externally-allocated input buffer object
pb
to the pipeline input. The buffer may be detached from the pipeline
using sd_DetachInput
.
The buffer object is provided as a convenience for languages/environments
that do not allow direct manipulation of memory chunks using
sd_AttachMemTo*
functions.
7.4. sd_BufAttachToOutput - Attach buffer object to the pipeline output (see below for data buffer object) ↩
int sd_BufAttachToOutput(prkernel* pk,int pind,prbuf* pb);
Input
pk
pointer to the prkernel structurepind
pipeline indexpb
pointer to theprbuf
object
Output
- status code (
SD_OK
orSD_ERROR
)
Description
sd_BufAttachToOutput
connects the externally-allocated buffer object pb
to the pipeline output.
The buffer may be detached from the pipeline using sd_DetachInput
.
7.5. sd_DetachInput - Detach memory attached to the pipeline input ↩
int sd_DetachInput(prkernel* pk,int pind);
Input
pk
pointer to the prkernel structurepind
pipeline index
Output
- status code (
SD_OK
orSD_ERROR
)
Description
sd_DetachInput
disconnects the memory attached to the pipeline input. User is responsible for freeing the memory she allocated.
7.6. sd_DetachOutput - Detach memory attached to the pipeline output ↩
int sd_DetachOutput(prkernel* pk,int pind);
Input
pk
pointer to the prkernel structurepind
pipeline index
Output
- status code (
SD_OK
orSD_ERROR
)
Description
sd_DetachOutput
disconnects the memory attached to the pipeline output. User is responsible for freeing the memory she allocated.
8. Pipeline execution ↩
8.1. sd_IsReadyToExecute ↩
int sd_IsReadyToExecute(prkernel* pk,int pind);
Input
pk
pointer to the prkernel structurepind
pipeline index
Output
SD_YES
orSD_NO
indicating whether pipeline is connected to application input and output buffers.
Description
Call sd_IsReadyToExecute
to test if some input and output application buffers are connected to the pipeline.
8.2. sd_Execute ↩
int sd_Execute(prkernel* pk,int pind);
Input
pk
pointer to the prkernel structurepind
pipeline index
Output
SD_OK
if successful
Description
sd_Execute
runs the pipeline pind
on the data from application buffer
attached to pipeline input and places the results into the result buffer
attached to pipeline output. In order to execute on new batch of data, it
is sufficient to place new values into the input buffer and re-run
sd_Execute
(the attach routines are not needed if the input/output
buffers don't change).
8.3. sd_SetOp Set classifier to a specific operating point ↩
int sd_SetOp(prkernel* pk,int pind,int cind,int opind);
Input
pk
pointer to the prkernel structurepind
pipeline indexcind
index of a classifier within the pipelinepind
opind
index of an operating point in the classifiercind
Output
- status (
SD_OK
orSD_ERROR
)
Description
sd_SetOp
allows one to change operating points in a pipeline between
sd_Execute
calls. Single pipeline may contain multiple classifiers each
with its own set of operating points (e.g. the cascade pipeline with a
detector and discriminant).
8.4. sd_GetOp Get current operating point of a classifier ↩
int sd_GetOp(prkernel* pk,int pind,int cind);
Input
pk
pointer to the prkernel structurepind
pipeline indexcind
index of a classifier within the pipelinepind
Output
- operating point index or
SD_ERROR
in case of error
Description
sd_GetOp
retrieves a current operating points in a specific loaded
pipeline.
8.5. sd_GetOpCount Retrieve number of classifier operating points ↩
int sd_GetOpCount(prkernel* pk,int pind,int cind);
Input
pk
pointer to the prkernel structurepind
pipeline indexcind
index of a classifier within the pipelinepind
Output
- number of operating points or
SD_ERROR
Description
sd_GetOpCount
retrieves a number of operating points available in a
classifier with index cind
in a loaded pipeline pind
.
8.6. sd_GetClassifierCount Retrieve number of classifiers in a pipeline ↩
int sd_GetClassifierCount(prkernel* pk,int pind);
Input
pk
pointer to the prkernel structurepind
pipeline index
Output
- number of classifiers or
SD_ERROR
Description
Single pipeline may contain multiple classifiers (for example cascaded
pipeline has several stages, or classifier combiner several base
classifiers). perClass allows us to set operating point of each classifier
in a pipeline independently via sd_SetOp
using classifier index cind
.
The sd_GetClassifierCount
retrieves the number of classifiers clfc
available in a pipeline pind
. The classifier index is 0
to clfc-1
.
9. Data buffers ↩
9.1. sd_BufNew Allocate memory buffer ↩
prbuf* sd_BufNew(int type,int sc,int fc);
Input
type
of data (SDDOUBLE, SDSINGLE or SD_INT)sc
number of allocated samplesfc
number of features
Output
pb
pointer to aprbuf
buffer object
9.2. sd_BufNewReferringTo - Create buffer refering to existing application memory chunk ↩
prbuf* sd_BufNewReferringTo(int type, void* data,int sc,int fc,int so,int fo);
Input
type
of data (SDDOUBLE, SDSINGLE, SD_INT)data
pointer to data buffersc
number of samplesfc
number of features
Output
pb
pointer to aprbuf
buffer object
Description
sd_BufNewReferringTo
constructs a buffer object representing a memory
area allocated by the application. Releasing this memory after destructing
the buffer object using sd_BufFree is user's responsibility. The function
assumes sample-per-sample memory scheme (all features of the same sample
are stored together).
9.3. sd_BufLoadFromCSVFile - Allocate a buffer and fill it with data from a comma-separated file ↩
prbuf* sd_BufLoadFromCSVFile(char* filename);
Input
filename
pointer to string buffer with file name
Output
pb
pointer to aprbuf
buffer object
Description
sd_BufLoadFromCSVFile
constructs a buffer object from comma-separated file.
9.4. sd_BufFree - Free a buffer ↩
void sd_BufFree(prbuf* pb);
Input
pb
a buffer object
Description
sd_BufFree
releases the buffer object. The underlying memory area is
freed only if it was allocated by the perClass runtime. This holds for
buffers created using sd_BufNew
and sd_BufLoadFromCSVFile
functions. It
is user's responsibility to free the memory passed to the
sd_BufNewReferringTo
call.
9.5. sd_BufGetSc - Return the number of samples in a buffer ↩
int sd_BufGetSc(prbuf* pb);
Input
pb
a buffer object
Output
- number of samples in the buffer
Description
sd_BufGetSc
returns the number of samples stored in the buffer pb
. By default, this is the allocated number of samples. User may, set the actual number of buffer samples using sd_BufSetSc
.
9.6. sd_BufSetSc - Set the number of actual samples in the allocated buffer ↩
Input
pb
a buffer objectsc
actual number of samples
Output
- status (
SD_OK
orSD_ERROR
)
Description
sd_BufSetSc
allows one to set the number of actual samples stored in the
buffer which is smaller or equal than the allocated number of samples.
This allows us to allocate enough space for works-case scenario but process
in each iteration only the samples actually generated by our data
acquisution process.
9.7. sd_BufGetFc - Return the number of features in a buffer ↩
int sd_BufGetFc(prbuf* pb)
Input
pb
a buffer object
Output
- number of buffer features
10. Getting/Setting values in a buffer ↩
10.1. sd_BufGetValueDouble ↩
double sd_BufGetValueDouble(prbuf* pb,int sample,int feature)
Input
pb
a buffer objectsample
zero-based sample indexfeature
zero-based feature index
Output
- value from the buffer object
10.2. sd_BufGetValueSingle ↩
double sd_BufGetValueSingle(prbuf* pb,int sample,int feature)
Input
pb
a buffer objectsample
zero-based sample indexfeature
zero-based feature index
Output
- value from the buffer object
10.3. sd_BufGetValueInt ↩
double sd_BufGetValueInt(prbuf* pb,int sample,int feature)
Input
pb
a buffer objectsample
zero-based sample indexfeature
zero-based feature index
Output
- value from the buffer object
10.4. sd_BufSetValueDouble ↩
void sd_BufSetValueDouble(prbuf* pb,int sample,int feature,double value)
Input
pb
a buffer objectsample
zero-based sample indexfeature
zero-based feature indexvalue
10.5. sd_BufSetValueSingle ↩
void sd_BufSetValueSingle(prbuf* pb,int sample,int feature,float value)
Input
pb
a buffer objectsample
zero-based sample indexfeature
zero-based feature indexvalue
10.6. sd_BufSetValueInt ↩
void sd_BufSetValueInt(prbuf* pb,int sample,int feature,int value)
Input
pb
a buffer objectsample
zero-based sample indexfeature
zero-based feature indexvalue
11. Cross-platform precision timers ↩
11.1. sd_Tic - Start precision timer ↩
void sd_Tic(prkernel* pk)
Input
pk
pointer to the prkernel structure
sd_Tic
starts a precision timer. Subsequent call to sd_Toc
returns the
time in seconds. The sd_Tic
and sd_Toc
calls are not reentrant
i.e. should not be nested or called concurently from different threads.
11.2. sd_Toc - Stop precision timer ↩
double sd_Toc(prkernel* pk)
Input
pk
pointer to the prkernel structure
Output
- time in seconds since last cal of
sd_Tic