C:/programs/etirm/src/swig_etirm.cpp

Go to the documentation of this file.
00001 /*! \file swig_etirm.cpp
00002  
00003   \brief
00004   Definitions of functions and classes to generate scripting language wrapper 
00005   functions for ETIRM using SWIG.
00006 
00007   The file swig_etirm_types.h (which is included in swig_etirm.h) must be 
00008   provided which should contain typedef's for the following types:
00009  
00010   ResponseVector  Vector containing item responses.
00011   item_type   Item class.
00012   examinee_type Examinee class.
00013   lvdist_type   Latent variable distribution class.
00014   random_type   Type of random number generator used for bootstrap.
00015 
00016   For example:
00017 
00018   // Do not process with SWIG, SWIG cannot handle the template arguments
00019   xx_ifndef SWIG
00020  
00021   // Vector of item responses
00022   typedef std::vector<etirm::Response> ResponseVector;
00023  
00024   // Class to hold information about discrete latent variable distribution
00025   typedef etirm::DiscreteLatentDist<etirm::Real> lvdist_type;
00026  
00027   // Class to hold information about examinees
00028   typedef etirm::ExamineeGrpCov<ResponseVector, etirm::RealVector> examinee_type;
00029  
00030   // Type used for array of items. Using ItemNR allows different items to be modeled
00031   // by different classes descendent from ItemNR (e.g., the 3PL model could be used for
00032   // some items, and the 2PL model used for other items).
00033   typedef etirm::ItemNR<lvdist_type> item_type;
00034  
00035   // Use the Mersenne Twister (http://www.math.keio.ac.jp/matumoto/emt.html)
00036   // from the Boost random number library
00037   // (http://www.boost.org/libs/random/index.html) 
00038   // as random number generator for bootstrap samples.
00039   typedef boost::mt19937 random_type;
00040 
00041   xx_endif // SWIG
00042  
00043   An application using these wrapper functions should declare a subclass
00044   of SwigEtirmRun whose constructor initializes the item object pointers, and 
00045   assigns them to the 'items' data member of SwigEtirmRun. 
00046   An application should provide functions for creating and deleting an object
00047   that is a subclass of SwigEtirmRun which is stored in the global variable
00048   gEtirmRun defined in this file.
00049 
00050   Definitions of the function CheckRunInit must be provided. This
00051   function is declared in swig_etirm.h, but each application must define it.
00052   It is not defined in swig_etirm.cpp.
00053  
00054   The function CheckRunInit checks whether gEtirmRun has been
00055   initialized, and if not throws an exception. The message contained
00056   in the exception will differ for different applications. 
00057 
00058   Estimation Toolkit for Item Response Models (ETIRM)
00059   http://www.smallwaters.com/software/cpp/etirm.html
00060 
00061   Author(s): 
00062   Werner Wothke, maintenance (http://www.smallwaters.com)
00063   Brad Hanson (http://www.b-a-h.com/)
00064   See the file LICENSE for information on usage and redistribution.
00065 
00066   Copyright (C) 2008, Werner Wothke
00067   Copyright (c) 2000-2002, Bradley A. Hanson
00068  */
00069 
00070 #ifdef ETIRM_NO_DIR_PREFIX
00071 #include "swig_etirm.h"
00072 #include "MStepIRT.h"
00073 #include "DiscreteNormalDist.h"
00074 #include "ItemParamPriorBeta4.h"
00075 #include "ItemParamPriorLogNormal.h"
00076 #include "ItemParamPriorNormal.h"
00077 #include "BootstrapSample.h"
00078 #include "SimulateResponses.h"
00079 #include "ExamineeThetaMLE.h"
00080 #else
00081 #include "etirm/swig_etirm.h"
00082 #include "etirm/MStepIRT.h"
00083 #include "etirm/DiscreteNormalDist.h"
00084 #include "etirm/ItemParamPriorBeta4.h"
00085 #include "etirm/ItemParamPriorLogNormal.h"
00086 #include "etirm/ItemParamPriorNormal.h"
00087 #include "etirm/BootstrapSample.h"
00088 #include "etirm/SimulateResponses.h"
00089 #include "etirm/ExamineeThetaMLE.h"
00090 #endif
00091 
00092 // Use integer random number generator from boost library
00093 // (http://www.boost.org).
00094 #include <boost/random/uniform_int.hpp>
00095 
00096 #include <cstdio>  // sprintf prototype
00097 // for compilers which do not put C library functions in std namespace
00098 #ifdef BOOST_NO_STDC_NAMESPACE
00099 namespace std
00100 { using ::sprintf;}
00101 #endif
00102 
00103 // Definitions not wrapped by SWIG
00104 namespace etirm
00105 {
00106 
00107   //! Global variable holding information about a run.
00108   SwigEtirmRun *gEtirmRun = 0;
00109 
00110   /*!
00111     \brief
00112     Increments counts based on item response.
00113    
00114     \section function_args Function Parameters
00115    
00116     \param[in]  respIndex "One" offset index corresponding to response to increment 
00117         count for (1 = first response category, 2 = second response category, etc.).
00118     \param[in]  count   Amount to increment counts.
00119     \param[in]  group   Group to increment counts for (1, 2, ...).
00120    */
00121   void ItemRespCounts::AddResponse(int respIndex, Real count, int group)
00122   {
00123 
00124     if (respIndex > catCounts.size() || respIndex < 1)
00125     {
00126       throw InvalidArgument("Invalid response index", "ItemRespCounts::AddResponse");
00127     }
00128 
00129     totalCount[0] += count; // total count
00130     totalCount[group] += count; // count for group
00131 
00132     catCounts(1, respIndex) += count; // total count
00133     catCounts(group+1, respIndex) += count; // count for group
00134   }
00135 
00136   /*!
00137     \brief
00138     Class constructor.
00139    
00140     \section function_args Function Parameters
00141    
00142     \param[in]  nitems    Total number of items.
00143     \param[in]  nlatentcat  Number of categories of discrete latent variable.
00144     \param[in]  ngroups   Number of examinee groups.
00145     \param[in]  minTheta  Minimum value of theta points for discrete latent 
00146         variable distribution.
00147     \param[in]  maxTheta  Maximum value of theta points for discrete latent 
00148         variable distribution.
00149     \param[in]  uniquePoints  If true then unique latent distribution points 
00150         are used for each examinee group.
00151    */
00152   SwigEtirmRun::SwigEtirmRun(int nitems, int nlatentcat, int ngroups, Real minTheta, Real maxTheta,
00153       bool uniquePoints) :
00154     numItems(nitems), numLatentCat(nlatentcat), numGroups(ngroups), examineeCounts(ngroups+1, 0.0),
00155         items(nitems), itemStats(nitems), minProc(nitems), latentDist(nlatentcat, ngroups,
00156             uniquePoints), rand_boot(0), base_rand_simulate(0), rand_simulate(0)
00157   {
00158     int i;
00159 
00160     // Set default points and weights for latent variable distribution to standard normal
00161     // for first group
00162     DiscreteNormalDist(nlatentcat, minTheta, maxTheta, latentDist.begin_points(1),
00163         latentDist.begin_weights(1));
00164 
00165     // Set points and weights for other groups equal to the points and weights for group 1
00166     for (i=2; i<=ngroups; ++i)
00167     {
00168       DiscreteLatentDist<Real>::weight_iterator w1 = latentDist.begin_weights(1);
00169       DiscreteLatentDist<Real>::weight_iterator w2 = latentDist.begin_weights(i);
00170       for (int j = nlatentcat; j--; ++w1, ++w2)
00171       {
00172         *w2 = *w1;
00173       }
00174 
00175       if (uniquePoints)
00176       {
00177         // initialize unique points for examinee group
00178         DiscreteLatentDist<Real>::point_iterator w1p = latentDist.begin_points(1);
00179         DiscreteLatentDist<Real>::point_iterator w2p = latentDist.begin_points(i);
00180         for (int j = nlatentcat; j--; ++w1p, ++w2p)
00181         {
00182           *w2p = *w1p;
00183         }
00184       }
00185     }
00186 
00187     /* initialize vectors of pointers to null */
00188     for (i=0; i<nitems; ++i)
00189     {
00190       items[i] = 0;
00191       itemStats[i] = 0;
00192       minProc[i] = 0;
00193     }
00194 
00195   }
00196 
00197   //! Releases memory allocated by constructor.
00198   SwigEtirmRun::~SwigEtirmRun()
00199   {
00200     int i;
00201 
00202     for (i=0; i<numItems; i++)
00203     {
00204       if (items[i])
00205       {
00206         items[i]->DeletePriors();
00207         delete items[i];
00208       }
00209 
00210       if (itemStats[i])
00211         delete itemStats[i];
00212       if (minProc[i])
00213         delete minProc[i];
00214     }
00215 
00216     int n = examinees.size();
00217     for (i=0; i<n; ++i)
00218     {
00219       delete examinees[i];
00220     }
00221 
00222     delete rand_boot;
00223     delete base_rand_simulate;
00224     delete rand_simulate;
00225   }
00226 
00227   // Check that data for examinees exist
00228   void SwigEtirmRun::CheckExaminees(const char *funcname)
00229   {
00230     if ((gEtirmRun->examinees).size() == 0)
00231     {
00232       throw RuntimeError("Error: No examinee data", funcname);
00233     }
00234   }
00235 
00236   // Check that examinee number is valid
00237   void SwigEtirmRun::CheckExamineeNumber(int examno, const char *funcname)
00238   {
00239     if ( (examno < 1) || ( examno > (gEtirmRun->examinees).size() ) )
00240     {
00241       char errstr[50];
00242       std::sprintf(errstr, "Invalid examinee number: %d", examno);
00243       gEtirmRun->returnString = errstr;
00244       throw RuntimeError((gEtirmRun->returnString).c_str(), funcname);
00245     }
00246   }
00247 
00248   // Check that item number is valid
00249   void SwigEtirmRun::CheckItemNumber(int itemno, const char *funcname)
00250   {
00251     if (itemno < 1 || itemno >(gEtirmRun->numItems) ) // Syntax edited, ww, 2-24-2008.
00252     {
00253       char errstr[50];
00254       std::sprintf(errstr, "Invalid item number: %d", itemno);
00255       gEtirmRun->returnString = errstr;
00256       throw RuntimeError((gEtirmRun->returnString).c_str(), funcname);
00257     }
00258   }
00259 
00260   // Check that group number is valid
00261   //  group   Value to check.
00262   //  funcname  Name of calling function (used in error message)
00263   void SwigEtirmRun::CheckGroup(int group, const char *funcname)
00264   {
00265     if (group < 1 || group >(gEtirmRun->numGroups) ) // Syntax edited, ww, 2-24-2008
00266     {
00267       char errstr[50];
00268       std::sprintf(errstr, "Invalid examinee group: %d", group);
00269       gEtirmRun->returnString = errstr;
00270       throw RuntimeError((gEtirmRun->returnString).c_str(), funcname);
00271     }
00272   }
00273 
00274   /*! 
00275     \brief
00276     Tests whether item parameter index is valid for the item.
00277    
00278     \section function_args Function Parameters
00279     
00280     \param[in]  *item   Pointer to item object for which index is checked.
00281     \param[in]  index   Zero-offset index of item parameter.
00282     \param[in]  *funcname pointer to name of calling function (used in error message).
00283    */
00284   void CheckItemParam(item_type *item, int index, const char *funcname)
00285   {
00286     if (item->NumParameters() <= index || index < 0)
00287     {
00288       char errstr[100];
00289       std::sprintf(errstr, "Invalid item parameter index for item %d: %d", item->Index()+1, index);
00290       gEtirmRun->returnString = errstr;
00291       throw RuntimeError((gEtirmRun->returnString).c_str(), funcname);
00292     }
00293   }
00294 
00295   /*!
00296     \brief
00297     Create a prior distribution object and return a pointer to it.
00298    
00299     \section function_args Function Parameters
00300 
00301     \param[in]  pstr  Type of prior distribution, valued as ("none", "normal", "lognormal", "beta").
00302     \param[in]  priorparam  Parameters of prior distribution.
00303     \param[in]  funcname  Name of calling function (used in error messages)
00304    */
00305   ItemParamPrior *CreatePrior(const std::string &pstr, const double_vector &priorparam,
00306       const char *funcname)
00307   {
00308     const char *err_message = "Invalid number of prior parameters";
00309 
00310     if (pstr.compare("none") == 0)
00311     {
00312       return 0;
00313     }
00314     else if (pstr.compare("normal") == 0)
00315     {
00316       if (priorparam.size() != 2)
00317         throw RuntimeError(err_message, funcname);
00318       return new ItemParamPriorNormal(priorparam[0], priorparam[1]);
00319     }
00320     else if (pstr.compare("lognormal") == 0)
00321     {
00322       if (priorparam.size() != 2)
00323         throw RuntimeError(err_message, funcname);
00324       return new ItemParamPriorLogNormal(priorparam[0], priorparam[1]);
00325     }
00326     else if (pstr.compare("beta") == 0)
00327     {
00328       if (priorparam.size() != 4)
00329         throw RuntimeError(err_message, funcname);
00330       return new ItemParamPriorBeta4(priorparam[0], priorparam[1], priorparam[2], priorparam[3]);
00331     }
00332     else
00333     {
00334       throw RuntimeError("Invalid prior type", funcname);
00335     }
00336     return 0;
00337   }
00338 
00339   /*!
00340     \brief
00341     Converts a response for an item into a character, where '0' represents the 
00342     first response, '1' represents the second response, etc.
00343    
00344     If the number of response categories for the item is greater than 10, then the 
00345     characters returned will be ascii characters greater than '9'. For example, a 
00346     ':' is return for a response in response category 11, since ':' is one greater
00347     than '9' in the ascii sequence.
00348 
00349     \section function_args Function Parameters
00350     
00351     \param[in]  r Item response to be converted.
00352     \param[in]  *item Pointer to item object.
00353    */
00354   char Resp2Char(Response r, const item_type *item)
00355   {
00356     const char zero = '0';
00357     Response np = item_type::NotPresentedResponse();
00358     char cr;
00359     if (r == np)
00360       cr = np - item->FirstResponse() + zero;
00361     else
00362       cr = item->ResponseIndex(r) + zero;
00363 
00364     return cr;
00365   }
00366 
00367   /****** Functions for which SWIG wrappers are generated ******/
00368 
00369   /* Member functions for estep class */
00370 
00371   /*!
00372     \brief
00373     Initialize estep object.
00374    
00375     \section function_args Function Parameters
00376    
00377     \param[in]  *itemno Pointer to list of item numbers to use for computing 
00378     examinee posteriors distribution in E-Step. If itemno = NUL, use all items (default).
00379    */
00380   estep::estep(int_vector *itemno)
00381   {
00382     CheckRunInit();
00383 
00384     if (itemno)
00385     {
00386       mItems = new ItemVector(ItemSubset(itemno,gEtirmRun->items,"new_estep"));
00387 
00388       mEStep = new estep_type(mItems->begin(), mItems->end(), gEtirmRun->latentDist);
00389     }
00390     else
00391     {
00392       mItems = 0;
00393       mEStep = new estep_type((gEtirmRun->items).begin(), (gEtirmRun->items).end(), gEtirmRun->latentDist);
00394     }
00395   }
00396 
00397   /*!
00398     \brief
00399     Release memory allocated in constructor.
00400    */
00401   estep::~estep()
00402   {
00403     if (mItems)
00404       delete mItems;
00405     delete mEStep;
00406   }
00407 
00408   /*!
00409     \brief
00410     Calls mEStep->DoEStep to perform E-step.
00411    
00412     Returns marginal loglikelihood of examinees' responses (sum over examinees of the 
00413     marginal loglikelihood of an examinee's responses) plus sum of prior likelihoods 
00414     over all item parameters.  This is the value of the marginal posterior density that 
00415     the EM algorithm is maximizing at the values of the item parameters computed in the 
00416     last M-step.
00417    
00418     \section function_args Function Parameters
00419    
00420     \param[in]  compute_post  Flag: If compute_post == TRUE, then compute posterior 
00421     distributions for all examinees. If compute_post == FALSE, then use previously 
00422     stored posteriors for examinees. (Default: TRUE).
00423    
00424     \param[in]  store_post  Flag: If store_post == TRUE, then store the posterior 
00425     distribution computed for each examinee. These posterior distributions are 
00426     stored as part of the examinee objects.
00427     (Default: FALSE).
00428    
00429     \param[in]  *estep_items  Pointer to list of items for which n and r are updated. If a 
00430     null pointer is passed then n arnd r are updated for all items used in the E-step 
00431     to compute examinee posterior distributions.
00432    */
00433   double estep::compute(bool compute_post, bool store_post, int_vector *estep_items) // compute_post and store_post retyped as "bool", ww, 2-24-2008.
00434   {
00435     const char *fname = "estep_compute";
00436     CheckRunInit();
00437     gEtirmRun->CheckExaminees(fname);
00438 
00439     if (estep_items)
00440     {
00441       if (estep_items->size() > 0)
00442       {
00443         ItemVector itemsub = ItemSubset(estep_items, gEtirmRun->items, fname);
00444         return mEStep->DoEStep((gEtirmRun->examinees).begin(), (gEtirmRun->examinees).end(), itemsub.begin(), itemsub.end(), compute_post, store_post);
00445       }
00446       else // do not update n and r for any items
00447       {
00448         return mEStep->DoEStep((gEtirmRun->examinees).begin(), (gEtirmRun->examinees).end(), (gEtirmRun->items).begin(), (gEtirmRun->items).begin(), compute_post, store_post);
00449       }
00450     }
00451     else
00452     {
00453       return mEStep->DoEStep((gEtirmRun->examinees).begin(), (gEtirmRun->examinees).end(), compute_post, store_post);
00454     }
00455   }
00456 
00457   /*!
00458     \brief
00459     Assigns missing response code to identify examinees who did not respond to an item.
00460    */
00461   void set_missing_resp(char nr)
00462   {
00463     if (gEtirmRun)
00464     {
00465       throw RuntimeError("The not presented response can only be set before any items are initialized", 0);
00466     }
00467     Item<Real>::SetNotPresentedResponse(nr);
00468   }
00469 
00470   /*!
00471     \brief
00472     Returns the number of items.
00473    */
00474   int num_items()
00475   {
00476     CheckRunInit();
00477 
00478     return gEtirmRun->numItems;
00479   }
00480 
00481   /*!
00482     \brief
00483     Returns number of categories of the discrete theta distribution.
00484    */
00485   int num_latent_dist_points()
00486   {
00487     CheckRunInit();
00488 
00489     return gEtirmRun->numLatentCat;
00490   }
00491 
00492   /*!
00493     \brief
00494     Returns number of examinee groups.
00495    */
00496   int num_groups()
00497   {
00498     CheckRunInit();
00499 
00500     return gEtirmRun->numGroups;
00501   }
00502 
00503   /*!
00504     \brief
00505     Returns number of examinees.
00506    */
00507   int num_examinees()
00508   {
00509     CheckRunInit();
00510 
00511     return (gEtirmRun->examinees).size();
00512   }
00513 
00514   /*!
00515     \brief
00516     Returns the name of model used for an item.
00517    
00518     \section function_args Function Parameters
00519    
00520     \param[in]  itemno Item number (1-offset).
00521    */
00522   const char * item_get_model(int itemno)
00523   {
00524 
00525     CheckRunInit();
00526     std::string &modelName = gEtirmRun->returnString;
00527     gEtirmRun->CheckItemNumber(itemno, "item_get_model");
00528 
00529     item_type *item = (gEtirmRun->items)[itemno-1];
00530     modelName = item->ModelName();
00531 
00532     return modelName.c_str();
00533   }
00534 
00535   /*!
00536     \brief
00537     Assigns a value to one item parameter of an item.
00538    
00539     \section function_args Function Parameters
00540    
00541     \param[in] paramno  1-offset index of parameter in parameter vector for item.
00542     \param[in] itemno   Item number (1-offset).
00543     \param[in] paramvalue Value parameter is set to.
00544    */
00545   void item_set_param(int paramno, int itemno, double paramvalue)
00546   {
00547     const char *fname = "item_set_param";
00548     CheckRunInit();
00549     int index = paramno - 1;
00550 
00551     gEtirmRun->CheckItemNumber(itemno, fname);
00552     item_type *item = (gEtirmRun->items)[itemno-1];
00553     CheckItemParam(item, index, fname);
00554 
00555     /* Check that value of parameter has nonzero prior density */
00556     item_type::prior_iterator pri = item->PriorsIterator() + index;
00557     if (*pri && (*pri)->ZeroDensity(paramvalue))
00558     {
00559       char merr[100];
00560       std::sprintf(merr, "Parameter specified for item %d has zero prior density", itemno);
00561       gEtirmRun->returnString = merr;
00562       throw RuntimeError((gEtirmRun->returnString).c_str(), fname);
00563     }
00564 
00565     item_type::param_iterator pv = item->ParametersIterator();
00566 
00567     pv[index] = paramvalue;
00568   }
00569 
00570   /*!
00571     \brief
00572     Assigns values to all item parameters of an item.
00573    
00574     \section function_args Function Parameters
00575    
00576     \param[in]  itemno  Item number (1-offset).
00577     \param[in]  *params  Pointer to params vector containing the values to set the 
00578         parameters to.
00579    
00580     Note: The order of the parameters in the params vector is: 
00581     a (if there is an a parameter), one or more b's, and
00582     c (if there is a c parameter).
00583    */
00584   void item_set_params(int itemno, double_vector *params)
00585   {
00586     const char *fname = "item_set_params";
00587     CheckRunInit();
00588     gEtirmRun->CheckItemNumber(itemno, fname);
00589 
00590     item_type *item = (gEtirmRun->items)[itemno-1];
00591 
00592     // Assign new parameters
00593     item_type::param_iterator pv = item->ParametersIterator();
00594     double_vector::iterator iv = params->begin();
00595     int n;
00596     for (n = item->NumParameters(); n--; ++pv, ++iv)
00597     {
00598       *pv = *iv;
00599     }
00600 
00601     /* Check that values of all parameters have nonzero prior density */
00602     iv = params->begin();
00603     item_type::prior_iterator pri = item->PriorsIterator();
00604     for (n = item->NumParameters(); n--; ++pri, ++iv)
00605     {
00606       if (*pri && (*pri)->ZeroDensity(*iv))
00607       {
00608         char merr[100];
00609         std::sprintf(merr, "Parameter specified for item %d has zero prior density", itemno);
00610         throw InvalidArgument(merr, fname);
00611       }
00612     }
00613   }
00614 
00615   /*!
00616     \brief
00617     Assigns values to all fixed and estimated item parameters of an item.
00618    
00619     \section function_args Function Parameters
00620    
00621     \param[in]  itemno  Item number (1-offset).
00622     \param[in]  *params  Pointer to params vector containing the values to set the 
00623         parameters to.
00624    
00625     Note: The order of the parameters in the params vector is: 
00626     a (if there is an a parameter), one or more b's, and
00627     c (if there is a c parameter).
00628    */
00629   void item_set_all_params(int itemno, double_vector *params)
00630   {
00631     const char *fname = "item_set_all_params";
00632     CheckRunInit();
00633     gEtirmRun->CheckItemNumber(itemno, fname);
00634 
00635     item_type *item = (gEtirmRun->items)[itemno-1];
00636 
00637     // Assign new fixed and estimated parameters
00638     item->SetAllParameters(*params);
00639 
00640     /* Check that values of estimated parameters all have nonzero prior density */
00641     item_type::param_iterator iv = item->ParametersIterator();
00642     item_type::prior_iterator pri = item->PriorsIterator();
00643     for (int n = item->NumParameters(); n--; ++pri, ++iv)
00644     {
00645       if (*pri && (*pri)->ZeroDensity(*iv))
00646       {
00647         char merr[100];
00648         std::sprintf(merr, "Parameter specified for item %d has zero prior density", itemno);
00649         gEtirmRun->returnString = merr;
00650         throw InvalidArgument((gEtirmRun->returnString).c_str(), fname);
00651       }
00652     }
00653   }
00654 
00655   /*!
00656     \brief
00657     Returns value of one item parameter of an item.
00658    
00659     \section function_args Function Parameters
00660     
00661     \param[in]  paramno  1-offset index of the parameter in the item's parameter vector.
00662     \param[in]  itemno  Item number (1-offset).
00663    
00664     Note: The order of the parameters in the params vector is: 
00665     a (if there is an a parameter), one or more b's, and
00666     c (if there is a c parameter).
00667    */
00668   double item_get_param(int paramno, int itemno)
00669   {
00670     const char *fname = "item_get_param";
00671     CheckRunInit();
00672     int index = paramno - 1;
00673 
00674     gEtirmRun->CheckItemNumber(itemno, fname);
00675     item_type *item = (gEtirmRun->items)[itemno-1];
00676     CheckItemParam(item, index, fname);
00677 
00678     item_type::param_iterator pv = item->ParametersIterator();
00679 
00680     return pv[index];
00681   }
00682 
00683   /*!
00684     \brief
00685     Returns vector of all estimated item parameters values of an item.
00686    
00687     \section function_args Function Parameters
00688    
00689     \param[in]  itemno  Item number (1-offset).
00690    
00691     Note: The order of the parameters in the params vector is: 
00692     a (if there is an a parameter), one or more b's, and
00693     c (if there is a c parameter).
00694    */
00695   double_vector *item_get_params(int itemno)
00696   {
00697     CheckRunInit();
00698     gEtirmRun->CheckItemNumber(itemno, "item_get_params");
00699 
00700     item_type *item = (gEtirmRun->items)[itemno-1];
00701 
00702     int n = item->NumParameters();
00703     double_vector *params = new double_vector(n);
00704 
00705     item_type::param_iterator pv = item->ParametersIterator();
00706     double_vector::iterator iv = params->begin();
00707     for (; n--; ++pv, ++iv)
00708     {
00709       *iv = *pv;
00710     }
00711 
00712     return params;
00713   }
00714 
00715   /*!
00716     \brief
00717     Returns vector of all fixed and estimated item parameters values of an item.
00718    
00719     \section function_args Function Parameters
00720    
00721     \param[in]  itemno  Item number (1-offset).
00722    
00723     Note: The order of the parameters in the params vector is: 
00724     a (if there is an a parameter), one or more b's, and
00725     c (if there is a c parameter).
00726    */
00727   double_vector *item_get_all_params(int itemno)
00728   {
00729     CheckRunInit();
00730     gEtirmRun->CheckItemNumber(itemno, "item_get_all_params");
00731 
00732     item_type *item = (gEtirmRun->items)[itemno-1];
00733 
00734     RealVector allparam = item->GetAllParameters();
00735     int n = allparam.size();
00736     double_vector *params = new double_vector(n);
00737 
00738     RealVector::iterator pv = allparam.begin();
00739     double_vector::iterator iv = params->begin();
00740     for (; n--; ++pv, ++iv)
00741     {
00742       *iv = *pv;
00743     }
00744 
00745     return params;
00746   }
00747 
00748   /*!
00749     \brief
00750     Returns the number of parameters of an item.
00751 
00752     \section function_args Function Parameters
00753    
00754     \param[in]  itemno  Item number (1-offset).
00755    */
00756   int item_num_params(int itemno)
00757   {
00758     CheckRunInit();
00759     gEtirmRun->CheckItemNumber(itemno, "item_num_params");
00760 
00761     item_type *item = (gEtirmRun->items)[itemno-1];
00762 
00763     return item->NumParameters();
00764   }
00765 
00766   /*!
00767     \brief
00768     Returns the number of response categories of an item.
00769 
00770     \section function_args Function Parameters
00771    
00772     \param[in]  itemno  Item number (1-offset).
00773    */
00774   int item_num_resp_cat(int itemno)
00775   {
00776     CheckRunInit();
00777     gEtirmRun->CheckItemNumber(itemno, "item_num_resp_cat");
00778 
00779     item_type *item = (gEtirmRun->items)[itemno-1];
00780 
00781     return item->NumRespCat();
00782   }
00783 
00784   /*!
00785     \brief
00786     Assigns prior distribution parameters for one item parameter.
00787 
00788     \section function_args Function Parameters
00789    
00790     \param[in]  paramno 1-offset index of parameter in parameter vector for item.
00791     \param[in]  itemno  Number of item for which prior is set (1-offset).
00792     \param[in]  *priortype Pointer to type of prior distribution ("normal", "lognormal", "beta", "none").
00793     \param[in]  *dlist Pointer to vector of prior distribution parameters.
00794    */
00795   void item_set_prior(int paramno, int itemno, char *priortype, double_vector *dlist)
00796   {
00797     const char *funcname = "item_set_prior";
00798     CheckRunInit();
00799     int index = paramno - 1;
00800 
00801     gEtirmRun->CheckItemNumber(itemno, funcname);
00802     item_type *item = (gEtirmRun->items)[itemno-1];
00803     CheckItemParam(item, index, funcname);
00804 
00805     item_type::prior_iterator pv = item->PriorsIterator() + index;
00806 
00807     if (*pv)
00808       delete *pv;
00809 
00810     std::string pstr(priortype);
00811     *pv = CreatePrior(pstr, *dlist, funcname);
00812   }
00813 
00814   /*!
00815     \brief
00816     Returns type of prior distribution ("normal", "lognormal", "beta", "none")
00817     for one item parameter.
00818 
00819     \section function_args Function Parameters
00820    
00821     \param[in]  paramno 1-offset index of parameter in parameter vector for item.
00822     \param[in]  itemno  Number of item for which prior is returned (1-offset).
00823    */
00824   const char *item_get_prior_type(int paramno, int itemno)
00825   {
00826     const char *fname = "item_get_prior_type";
00827     CheckRunInit();
00828     std::string &priorName = gEtirmRun->returnString;
00829     int index = paramno - 1;
00830 
00831     gEtirmRun->CheckItemNumber(itemno, fname);
00832     item_type *item = (gEtirmRun->items)[itemno-1];
00833     CheckItemParam(item, index, fname);
00834 
00835     item_type::prior_iterator pv = item->PriorsIterator() + index;
00836 
00837     if (*pv != 0)
00838     {
00839       priorName = (*pv)->DistributionName();
00840     }
00841     else
00842     {
00843       priorName = "none";
00844     }
00845 
00846     return priorName.c_str();
00847   }
00848 
00849   /*!
00850     \brief
00851     Returns vector of prior distribution parameters for one item parameter.
00852 
00853     \section function_args Function Parameters
00854    
00855     \param[in]  paramno 1-offset index of parameter in parameter vector for item.
00856     \param[in]  itemno  Number of item for which prior is returned (1-offset).
00857    */
00858   double_vector *item_get_prior_param(int paramno, int itemno)
00859   {
00860     const char *fname = "item_get_prior_param";
00861     CheckRunInit();
00862     int index = paramno - 1;
00863 
00864     gEtirmRun->CheckItemNumber(itemno, fname);
00865     item_type *item = (gEtirmRun->items)[itemno-1];
00866     CheckItemParam(item, index, fname);
00867 
00868     item_type::prior_iterator pv = item->PriorsIterator() + index;
00869 
00870     double_vector *v;
00871     if (*pv != 0)
00872     {
00873       int n = (*pv)->NumParameters();
00874 
00875       v = new double_vector(n);
00876 
00877       *v = (*pv)->GetParameters();
00878     }
00879     else
00880     {
00881       v = new double_vector();
00882     }
00883 
00884     return v;
00885   }
00886 
00887   /*!
00888     \brief
00889     Returns vector of response counts in each response category of an item.
00890    
00891     \section function_args Function Parameters
00892    
00893     \param[in]  itemno  Number of item for which response counts are returned (1-offset).
00894     \param[in]  group Group to return counts for (1-offset). Specify group = 0 to return 
00895         counts across all groups.
00896    */
00897   double_vector *item_cat_counts(int itemno, int group)
00898   {
00899     const char *fname = "item_cat_counts";
00900     CheckRunInit();
00901 
00902     gEtirmRun->CheckItemNumber(itemno, fname);
00903     if (group != 0)
00904       gEtirmRun->CheckGroup(group, "item_resp_count");
00905 
00906     ItemRespCounts *stats = (gEtirmRun->itemStats)[itemno-1];
00907 
00908     double_vector *v = new double_vector(stats->CategoryCounts(group));
00909 
00910     return v;
00911   }
00912 
00913   /*!
00914     \brief
00915     Returns the number of examinees responding to an item.
00916    
00917     \section function_args Function Parameters
00918    
00919     \param[in]  itemno  Number of item for which response counts are returned (1-offset).
00920     \param[in]  group Group to return counts for (1-offset). Specify group = 0 to return 
00921         count across all groups.
00922    */
00923   double item_resp_count(int itemno, int group)
00924   {
00925     CheckRunInit();
00926 
00927     gEtirmRun->CheckItemNumber(itemno, "item_resp_count");
00928     if (group != 0)
00929       gEtirmRun->CheckGroup(group, "item_resp_count");
00930 
00931     return (gEtirmRun->itemStats)[itemno-1]->RespCount(group);
00932   }
00933   /*!
00934     \brief
00935     Transforms the parameter estimates of an item to a different latent variable scale.
00936    
00937     Returns zero if parameters are successfully scaled, or returns nonzero if
00938     scaling would result in an invalid parameter value.   
00939 
00940     \section function_args Function Parameters
00941    
00942     \param[in]  itemno  Number of item for which to transform parameters (1-offset).
00943     \param[in]  slope  Slope of scale transformation to apply to item parameters.
00944     \param[in]  intercept Intercept of scale transformation to apply to item parameters.
00945     \param[in]  ignorePriorError  If true then do not report an error if transformed parameter
00946         has zero density in prior used for that parameter.
00947    */
00948   int item_scale_params(int itemno, double slope, double intercept, bool ignorePriorE