@@ -178,21 +178,23 @@ void AlignableVolume::writeParameters(std::ostream& os) const
178178 if (isRoot ()) {
179179 os << " Parameter\n " ;
180180 }
181- if (mRigidBody ) {
182- for (int iDOF = 0 ; iDOF < mRigidBody ->nDOFs (); ++iDOF) {
183- os << std::format (" {:<10} {:>+15g} {:>+15g} ! {} {} " ,
184- mLabel .raw (iDOF), 0.0 , (mRigidBody ->isFree (iDOF) ? 0.0 : -1.0 ),
185- (mRigidBody ->isFree (iDOF) ? ' V' : ' F' ), mRigidBody ->dofName (iDOF))
186- << mSymName << ' \n ' ;
181+ if (!mIsPseudo ) {
182+ if (mRigidBody ) {
183+ for (int iDOF = 0 ; iDOF < mRigidBody ->nDOFs (); ++iDOF) {
184+ os << std::format (" {:<10} {:>+15g} {:>+15g} ! {} {} " ,
185+ mLabel .raw (iDOF), 0.0 , (mRigidBody ->isFree (iDOF) ? 0.0 : -1.0 ),
186+ (mRigidBody ->isFree (iDOF) ? ' V' : ' F' ), mRigidBody ->dofName (iDOF))
187+ << mSymName << ' \n ' ;
188+ }
187189 }
188- }
189- if ( mCalib ) {
190- auto calibLbl = mLabel . asCalib ();
191- for ( int iDOF = 0 ; iDOF < mCalib -> nDOFs (); ++iDOF) {
192- os << std::format ( " {:<10} {:>+15g} {:>+15g} ! {} {} " ,
193- calibLbl. raw (iDOF), 0.0 , (mCalib ->isFree (iDOF) ? 0.0 : - 1.0 ),
194- ( mCalib -> isFree (iDOF) ? ' V ' : ' F ' ), mCalib -> dofName (iDOF))
195- << mSymName << ' \n ' ;
190+ if ( mCalib ) {
191+ auto calibLbl = mLabel . asCalib ();
192+ for ( int iDOF = 0 ; iDOF < mCalib -> nDOFs (); ++iDOF) {
193+ os << std::format ( " {:<10} {:>+15g} {:>+15g} ! {} {:<5} " ,
194+ calibLbl. raw (iDOF), 0.0 , ( mCalib -> isFree (iDOF) ? 0.0 : - 1.0 ) ,
195+ (mCalib ->isFree (iDOF) ? ' V ' : ' F ' ), mCalib -> dofName (iDOF))
196+ << mSymName << ' \n ' ;
197+ }
196198 }
197199 }
198200 for (const auto & c : mChildren ) {
@@ -266,6 +268,9 @@ void applyDOFConfig(AlignableVolume* root, const std::string& jsonPath)
266268 }
267269
268270 root->traverse ([&](AlignableVolume* vol) {
271+ if (vol->isPseudo ()) {
272+ return ;
273+ }
269274 const std::string& sym = vol->getSymName ();
270275 for (const auto & rule : rules) {
271276 const auto pattern = rule[" match" ].get <std::string>();
@@ -357,6 +362,41 @@ void applyDOFConfig(AlignableVolume* root, const std::string& jsonPath)
357362 }
358363 }
359364 vol->setCalib (std::move (dofSet));
365+ } else if (calType == " inextensional" ) {
366+ int maxOrder = cal.value (" order" , 2 );
367+ auto dofSet = std::make_unique<InextensionalDOFSet>(maxOrder);
368+ bool fixed = cal.value (" fixed" , false );
369+ if (fixed) {
370+ dofSet->setAllFree (false );
371+ }
372+ if (cal.contains (" free" )) {
373+ dofSet->setAllFree (false );
374+ for (const auto & item : cal[" free" ]) {
375+ if (item.is_number_integer ()) {
376+ dofSet->setFree (item.get <int >(), true );
377+ } else if (item.is_string ()) {
378+ for (int k = 0 ; k < dofSet->nDOFs (); ++k) {
379+ if (dofSet->dofName (k) == item.get <std::string>()) {
380+ dofSet->setFree (k, true );
381+ }
382+ }
383+ }
384+ }
385+ }
386+ if (cal.contains (" fix" )) {
387+ for (const auto & item : cal[" fix" ]) {
388+ if (item.is_number_integer ()) {
389+ dofSet->setFree (item.get <int >(), false );
390+ } else if (item.is_string ()) {
391+ for (int k = 0 ; k < dofSet->nDOFs (); ++k) {
392+ if (dofSet->dofName (k) == item.get <std::string>()) {
393+ dofSet->setFree (k, false );
394+ }
395+ }
396+ }
397+ }
398+ }
399+ vol->setCalib (std::move (dofSet));
360400 }
361401 }
362402 }
@@ -398,6 +438,12 @@ void writeMillepedeResults(AlignableVolume* root, const std::string& milleResPat
398438 // indexed by sensorID
399439 std::map<int , std::vector<double >> injRB;
400440 std::map<int , std::vector<std::vector<double >>> injMatrix;
441+ struct InjInex {
442+ std::map<int , std::array<double , 4 >> modes;
443+ double alpha{0 .};
444+ double beta{0 .};
445+ };
446+ std::map<int , InjInex> injInex;
401447 if (!injectedJsonPath.empty ()) {
402448 std::ifstream injFile (injectedJsonPath);
403449 if (injFile.is_open ()) {
@@ -410,6 +456,22 @@ void writeMillepedeResults(AlignableVolume* root, const std::string& milleResPat
410456 if (item.contains (" matrix" )) {
411457 injMatrix[id] = item[" matrix" ].get <std::vector<std::vector<double >>>();
412458 }
459+ if (item.contains (" inextensional" )) {
460+ InjInex ii;
461+ const auto & inex = item[" inextensional" ];
462+ if (inex.contains (" modes" )) {
463+ for (auto & [key, val] : inex[" modes" ].items ()) {
464+ ii.modes [std::stoi (key)] = val.get <std::array<double , 4 >>();
465+ }
466+ }
467+ if (inex.contains (" alpha" )) {
468+ ii.alpha = inex[" alpha" ].get <double >();
469+ }
470+ if (inex.contains (" beta" )) {
471+ ii.beta = inex[" beta" ].get <double >();
472+ }
473+ injInex[id] = ii;
474+ }
413475 }
414476 LOGP (info, " Loaded injected misalignment for {} sensors" , injData.size ());
415477 } else {
@@ -468,6 +530,43 @@ void writeMillepedeResults(AlignableVolume* root, const std::string& milleResPat
468530 matrix.push_back (row);
469531 }
470532 entry[" matrix" ] = matrix;
533+ } else if (cal && cal->nFreeDOFs () && cal->type () == DOFSet::Type::Inextensional) {
534+ write = true ;
535+ auto * inexSet = static_cast <const InextensionalDOFSet*>(cal);
536+ int maxN = inexSet->maxOrder ();
537+ auto calibLbl = vol->getLabel ().asCalib ();
538+ const auto & inj = injInex.contains (id) ? injInex[id] : InjInex{};
539+
540+ json inexEntry;
541+ json modesObj = json::object ();
542+ for (int n = 2 ; n <= maxN; ++n) {
543+ int off = InextensionalDOFSet::modeOffset (n);
544+ std::array<double , 4 > injCoeffs = {0 ., 0 ., 0 ., 0 .};
545+ if (inj.modes .contains (n)) {
546+ injCoeffs = inj.modes .at (n);
547+ }
548+ json modeArr = json::array ();
549+ for (int k = 0 ; k < 4 ; ++k) {
550+ uint32_t raw = calibLbl.raw (off + k);
551+ auto it = labelToValue.find (raw);
552+ double fitted = it != labelToValue.end () ? it->second : 0.0 ;
553+ modeArr.push_back (fitted - injCoeffs[k]);
554+ }
555+ modesObj[std::to_string (n)] = modeArr;
556+ }
557+ inexEntry[" modes" ] = modesObj;
558+
559+ // alpha
560+ uint32_t rawAlpha = calibLbl.raw (inexSet->alphaIdx ());
561+ auto itA = labelToValue.find (rawAlpha);
562+ inexEntry[" alpha" ] = (itA != labelToValue.end () ? itA->second : 0.0 ) - inj.alpha ;
563+
564+ // beta
565+ uint32_t rawBeta = calibLbl.raw (inexSet->betaIdx ());
566+ auto itB = labelToValue.find (rawBeta);
567+ inexEntry[" beta" ] = (itB != labelToValue.end () ? itB->second : 0.0 ) - inj.beta ;
568+
569+ entry[" inextensional" ] = inexEntry;
471570 }
472571 if (write) {
473572 output.push_back (entry);
0 commit comments