From ac1b825ceb3133880cfbf311136c72893ecbb923 Mon Sep 17 00:00:00 2001 From: samo38 Date: Wed, 16 Oct 2024 15:42:12 -0600 Subject: [PATCH 1/6] us_mpi_analysis: replaced US_Tar with US_Archive --- programs/us_mpi_analysis/us_mpi_analysis.cpp | 23 +++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/programs/us_mpi_analysis/us_mpi_analysis.cpp b/programs/us_mpi_analysis/us_mpi_analysis.cpp index f2e8e6965..7c140d2f9 100644 --- a/programs/us_mpi_analysis/us_mpi_analysis.cpp +++ b/programs/us_mpi_analysis/us_mpi_analysis.cpp @@ -1,7 +1,7 @@ #include "us_mpi_analysis.h" #include "us_math2.h" #include "us_astfem_math.h" -#include "us_tar.h" +#include "us_archive.h" #include "us_memory.h" #include "us_sleep.h" #include "us_util.h" @@ -172,11 +172,12 @@ DbgLv(0) << "work_dir=" << work_dir; DbgLv(0) << "Us_Mpi_Analysis " << REVISION; // Unpack the input tarfile - US_Tar tar; - - int result = tar.extract( tarfile ); - - if ( result != TAR_OK ) abort( "Could not unpack " + tarfile ); + US_Archive archive; + bool ok = archive.extract( tarfile ); + if ( !ok ) { + QString error = archive.getError(); + abort( "Could not unpack\n " + error + "\n" + tarfile ); + } // Create a dedicated output directory and make sure it's empty // During testing, it may not always be empty @@ -2481,8 +2482,14 @@ DbgLv(0) << my_rank << ": model2.description" << model2.description; } // Create the archive file containing all outputs - US_Tar tar; - tar.create( "analysis-results.tar", files ); + US_Archive archive; + QString filename = "analysis-results.tar"; + bool ok = archive.compress( files, filename ); + if ( !ok ) { + QString error = archive.getError(); + abort( "Could not compress files\n " + error + "\n" + filename ); + } + for(int jf=0;jf Date: Wed, 16 Oct 2024 15:43:40 -0600 Subject: [PATCH 2/6] us_archive: add an optional string list to see the extracted file --- utils/us_archive.cpp | 10 +++++++++- utils/us_archive.h | 7 ++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/utils/us_archive.cpp b/utils/us_archive.cpp index 1cd773db8..e3818c2e7 100644 --- a/utils/us_archive.cpp +++ b/utils/us_archive.cpp @@ -2,8 +2,12 @@ #include "archive_entry.h" #include "archive.h" -bool US_Archive::extract(const QString& filename, const QString& path) { +bool US_Archive::extract(const QString& filename, const QString& path, QStringList* file_list) { + if ( file_list != nullptr ) { + file_list->clear(); + } + QStringList file_list_in; QDir dir; QFileInfo fino(filename); QString outpath = path.trimmed(); @@ -89,6 +93,7 @@ bool US_Archive::extract(const QString& filename, const QString& path) { } file.close(); emit itemExtracted(entry_path, target.absoluteFilePath()); + file_list_in << target.absoluteFilePath(); } else { error = "US_Archive: Error: Failed to open file: " + target.absolutePath(); archive_read_close(archive); @@ -102,6 +107,9 @@ bool US_Archive::extract(const QString& filename, const QString& path) { archive_read_close(archive); archive_read_free(archive); + if ( file_list != nullptr) { + file_list->append(file_list_in); + } return true; } diff --git a/utils/us_archive.h b/utils/us_archive.h index 09cd25e7a..77dad9706 100644 --- a/utils/us_archive.h +++ b/utils/us_archive.h @@ -14,10 +14,11 @@ class US_UTIL_EXTERN US_Archive : public QObject US_Archive() {}; //! \brief Method to extract archive file (Supported files: tar, tar.gz, tgz, tar.bz2, tar.xz, .zip). - //! \param archivePath Path to the archive file. - //! \param outputPath Path to where extracted data will be saved. Default is the path where the archive file is located. + //! \param archivePath Path to the archive file. + //! \param outputPath Path to where extracted data will be saved. Default is the path where the archive file is located. + //! \param outputFileList The optional output list of extracted files. //! \return True if file extraction is completed, false otherwise. - bool extract(const QString&, const QString& = ""); + bool extract(const QString&, const QString& = "", QStringList* = nullptr); //! \brief Method to compress files and folders into an archive file. //! \param sourcePathList List of all files and folders need to be compressed. No need to list the contents of folders. From 56e22ba731537a2b7c1328c14503c8ff160accc0 Mon Sep 17 00:00:00 2001 From: doluk <69309597+doluk@users.noreply.github.com> Date: Mon, 11 Nov 2024 15:37:39 +0100 Subject: [PATCH 3/6] Add apparent s and D as column, properly label columns as apparent and standardized s and D Signed-off-by: doluk <69309597+doluk@users.noreply.github.com> --- gui/us_predict1.cpp | 115 +++++++++++++++++++++++++++++--------------- gui/us_predict1.h | 11 +++-- 2 files changed, 82 insertions(+), 44 deletions(-) diff --git a/gui/us_predict1.cpp b/gui/us_predict1.cpp index 047ae1fab..4c6b07d07 100644 --- a/gui/us_predict1.cpp +++ b/gui/us_predict1.cpp @@ -99,7 +99,7 @@ US_Predict1::US_Predict1( US_Hydrosim& parm, SLOT ( viscosity ( const QString& ) ) ); controls->addWidget( le_viscosity, c_row++, 1 ); } - + US_Math2::data_correction( temperature, solution ); QPushButton* pb_vbar = us_pushbutton( tr( "vbar (20" ) + DEGC + ")" ); connect( pb_vbar, SIGNAL( clicked() ), SLOT( get_peptide() ) ); controls->addWidget( pb_vbar, c_row, 0 ); @@ -241,21 +241,22 @@ US_Predict1::US_Predict1( US_Hydrosim& parm, main->addLayout( top ); QGridLayout* values = new QGridLayout; - - QLabel* titles[ 8 ]; + titles[ 0 ] = us_label( tr( "Model:" ) ); - titles[ 1 ] = us_label( "s (sec)" ); - titles[ 2 ] = us_label( "D (cm2/sec)" ); + titles[ 1 ] = us_label( "sapp (S)" ); + titles[ 2 ] = us_label( "Dapp (cm2/sec)" ); titles[ 3 ] = us_label( "f" ); titles[ 4 ] = us_label( "f / f0" ); titles[ 5 ] = us_label( "a (Å)" ); titles[ 6 ] = us_label( "b (Å)" ); - titles[ 7 ] = us_label( tr( "Volume " ) + "(Å3)" ); + titles[ 7 ] = us_label( tr( "Volume" ) + " (Å3)" ); + titles[ 8 ] = us_label( "s20,w (S)" ); + titles[ 9 ] = us_label( "D20,w (cm2/sec)" ); int row = 0; - for ( int i = 0; i < 8; i++ ) + for ( int i = 0; i < 10; i++ ) { titles[ i ]->setAlignment( Qt::AlignCenter ); values->addWidget( titles[ i ], row, i ); @@ -268,7 +269,7 @@ US_Predict1::US_Predict1( US_Hydrosim& parm, lb_oblate [ 0 ] = us_label( tr( "Oblate:" ) ); lb_rod [ 0 ] = us_label( tr( "Long Rod:" ) ); - for ( int i = 0; i < 8; i++ ) + for ( int i = 0; i < 10; i++ ) { if ( i > 0 ) { @@ -508,6 +509,44 @@ void US_Predict1::mouseU( const QwtDoublePoint& p ) //debug(); } +void US_Predict1::calc_column( const QString& name, const QString& unit, int column_index, double sphere_val, + double prolate_val, double oblate_val, double rod_val, double multiplier) +{ + double min_value = min( min( sphere_val, prolate_val ), min( oblate_val, rod_val ) ) * multiplier; + double max_value = max( max( sphere_val, prolate_val ), max( oblate_val, rod_val ) ) * multiplier; + int log_min = (int) ( log10( min_value ) ) ; + int log_max = (int) ( log10( max_value ) ) ; + int power_of_ten = 1e+0; + char format_char = 'g'; + if ( abs( log_min - log_max ) <= 1 ) + { + power_of_ten = log_max; + format_char = 'f'; + } + else + { + power_of_ten = log_min; + } + power_of_ten *= -1; + if ( qFabs(max_value * multiplier * (double)pow(10, power_of_ten)) < 1 ) + { + power_of_ten += (power_of_ten != 0) ? power_of_ten / abs( power_of_ten ) : 1; + } + + titles[ column_index ] ->setText( name + ((unit.isEmpty())?"":" (" + unit + ")" )); + + if ( power_of_ten != 0 ) + { + titles[ column_index ] ->setText( name + " (" + QString("e%1%2"). + arg(power_of_ten > 0 ? '+' : '-').arg(qFabs(power_of_ten),2,'f', 0, '0') + ((unit.isEmpty())?"":" " + unit) + ")" ); + } + lb_sphere [ column_index ]->setText( QString::number( sphere_val * multiplier * (double)pow(10, power_of_ten), format_char, 4 ) ); + lb_prolate[ column_index ]->setText( QString::number( prolate_val * multiplier * (double)pow(10, power_of_ten), format_char, 4 ) ); + lb_oblate [ column_index ]->setText( QString::number( oblate_val * multiplier * (double)pow(10, power_of_ten), format_char, 4 ) ); + lb_rod [ column_index ]->setText( QString::number( rod_val * multiplier * (double)pow(10, power_of_ten), format_char, 4 ) ); + +} + void US_Predict1::update() { allparams.mw = mw; @@ -519,37 +558,35 @@ void US_Predict1::update() allparams.calculate( temperature ); - lb_sphere[ 1 ] ->setText( QString::number( allparams.sphere.s , 'e', 4 ) ); - lb_sphere[ 2 ] ->setText( QString::number( allparams.sphere.D , 'e', 4 ) ); - lb_sphere[ 3 ] ->setText( QString::number( allparams.sphere.f , 'e', 4 ) ); - lb_sphere[ 4 ] ->setText( QString::number( allparams.sphere.f_f0 , 'f', 4 ) ); - lb_sphere[ 5 ] ->setText( QString::number( allparams.sphere.a , 'e', 4 ) ); - lb_sphere[ 6 ] ->setText( QString::number( allparams.sphere.b , 'e', 4 ) ); - lb_sphere[ 7 ] ->setText( QString::number( allparams.sphere.volume , 'e', 4 ) ); - - lb_prolate[ 1 ]->setText( QString::number( allparams.prolate.s , 'e', 4 ) ); - lb_prolate[ 2 ]->setText( QString::number( allparams.prolate.D , 'e', 4 ) ); - lb_prolate[ 3 ]->setText( QString::number( allparams.prolate.f , 'e', 4 ) ); - lb_prolate[ 4 ]->setText( QString::number( allparams.prolate.f_f0 , 'f', 4 ) ); - lb_prolate[ 5 ]->setText( QString::number( allparams.prolate.a , 'e', 4 ) ); - lb_prolate[ 6 ]->setText( QString::number( allparams.prolate.b , 'e', 4 ) ); - lb_prolate[ 7 ]->setText( QString::number( allparams.prolate.volume, 'e', 4 ) ); - - lb_oblate[ 1 ] ->setText( QString::number( allparams.oblate.s , 'e', 4 ) ); - lb_oblate[ 2 ] ->setText( QString::number( allparams.oblate.D , 'e', 4 ) ); - lb_oblate[ 3 ] ->setText( QString::number( allparams.oblate.f , 'e', 4 ) ); - lb_oblate[ 4 ] ->setText( QString::number( allparams.oblate.f_f0 , 'f', 4 ) ); - lb_oblate[ 5 ] ->setText( QString::number( allparams.oblate.a , 'e', 4 ) ); - lb_oblate[ 6 ] ->setText( QString::number( allparams.oblate.b , 'e', 4 ) ); - lb_oblate[ 7 ] ->setText( QString::number( allparams.oblate.volume , 'e', 4 ) ); - - lb_rod[ 1 ] ->setText( QString::number( allparams.rod.s , 'e', 4 ) ); - lb_rod[ 2 ] ->setText( QString::number( allparams.rod.D , 'e', 4 ) ); - lb_rod[ 3 ] ->setText( QString::number( allparams.rod.f , 'e', 4 ) ); - lb_rod[ 4 ] ->setText( QString::number( allparams.rod.f_f0 , 'f', 4 ) ); - lb_rod[ 5 ] ->setText( QString::number( allparams.rod.a , 'e', 4 ) ); - lb_rod[ 6 ] ->setText( QString::number( allparams.rod.b , 'e', 4 ) ); - lb_rod[ 7 ] ->setText( QString::number( allparams.rod.volume , 'e', 4 ) ); + // fill every column with the calculated values + calc_column( "sapp", "S", 1, + allparams.sphere.s, allparams.prolate.s, allparams.oblate.s, allparams.rod.s, + 1e+13 / solution.s20w_correction ); + calc_column( "Dapp", "cm2/sec", 2, + allparams.sphere.D, allparams.prolate.D, allparams.oblate.D, allparams.rod.D, + 1 / solution.D20w_correction ); + calc_column( "f", "", 3, + allparams.sphere.f, allparams.prolate.f, allparams.oblate.f, allparams.rod.f, + 1 ); + calc_column( "f / f0", "", 4, + allparams.sphere.f_f0, allparams.prolate.f_f0, allparams.oblate.f_f0, allparams.rod.f_f0, + 1 ); + calc_column( "a", "Å", 5, + allparams.sphere.a, allparams.prolate.a, allparams.oblate.a, allparams.rod.a, + 1 ); + calc_column( "b", "Å", 6, + allparams.sphere.b, allparams.prolate.b, allparams.oblate.b, allparams.rod.b, + 1 ); + calc_column( "Volume", "Å3", 7, + allparams.sphere.volume, allparams.prolate.volume, allparams.oblate.volume, allparams.rod.volume, + 1 ); + calc_column( "s20,w", "S", 8, + allparams.sphere.s, allparams.prolate.s, allparams.oblate.s, allparams.rod.s, + 1e+13 ); + calc_column( "D20,w", "cm2/sec", 9, + allparams.sphere.D, allparams.prolate.D, allparams.oblate.D, allparams.rod.D, + 1 ); + if ( signal ) emit changed(); } diff --git a/gui/us_predict1.h b/gui/us_predict1.h index d68f585b6..5c6e77a5e 100644 --- a/gui/us_predict1.h +++ b/gui/us_predict1.h @@ -86,10 +86,11 @@ class US_GUI_EXTERN US_Predict1 : public US_WidgetsDialog QLineEdit* le_max_x; QLabel* lb_info; - QLabel* lb_sphere [ 8 ]; - QLabel* lb_prolate[ 8 ]; - QLabel* lb_oblate [ 8 ]; - QLabel* lb_rod [ 8 ]; + QLabel* titles [ 10 ]; + QLabel* lb_sphere [ 10 ]; + QLabel* lb_prolate[ 10 ]; + QLabel* lb_oblate [ 10 ]; + QLabel* lb_rod [ 10 ]; US_Plot* plotLayout; QwtPlot* plot; @@ -119,7 +120,7 @@ class US_GUI_EXTERN US_Predict1 : public US_WidgetsDialog void debug ( void ); void source_changed ( bool ); void get_solution ( void ); - + void calc_column ( const QString&, const QString&, int, double, double, double, double, double = 1.0 ); void update_buffer ( const US_Buffer ); void update_vbar ( const US_Analyte ); void update_max_x ( const QString& ); From 4674c49901490a2149b2c2146aec046393b0b688 Mon Sep 17 00:00:00 2001 From: samo38 Date: Fri, 15 Nov 2024 14:33:50 -0700 Subject: [PATCH 4/6] us_convert_gui.cpp :: take out referecne data for each channel separately when the wavelengths differ even if each channel has only one triple --- programs/us_convert/us_convert_gui.cpp | 60 +++++++++++++++----------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/programs/us_convert/us_convert_gui.cpp b/programs/us_convert/us_convert_gui.cpp index c1b96fe22..8f8ea9b21 100644 --- a/programs/us_convert/us_convert_gui.cpp +++ b/programs/us_convert/us_convert_gui.cpp @@ -5512,7 +5512,21 @@ void US_ConvertGui::PseudoCalcAvg( void ) if ( referenceDefined ) return; // Average calculation has already been done - if ( isMwl ) + bool is_mwl_data = false; + int temp_wvl = -1; + for ( int ii = 0; ii < outData.size(); ii++) { + int wvl = qRound(outData.at(ii)->scanData.first().wavelength); + if ( temp_wvl == -1) { + temp_wvl = wvl; + continue; + } + if ( temp_wvl != wvl) { + is_mwl_data = true; + break; + } + } + + if ( is_mwl_data ) { // Do calculations for each wavelength, if MWL PseudoCalcAvgMWL(); return; @@ -6058,12 +6072,13 @@ void US_ConvertGui::cancel_reference( void ) int wvoff = 0; int rscans = ExpData.RI_nscans; + int nwl_rip = ExpData.RIwvlns.size(); // Do the inverse operation and retrieve raw intensity data for ( int ii = 0; ii < outData.size(); ii++ ) { US_DataIO::RawData* currentData = outData[ ii ]; - if ( isMwl ) + if ( nwl_rip > 1 ) { // For MWL, profile is offset by wavelength int iwavl = out_triples[ ii ].section( " / ", 2, 2 ).toInt(); wvoff = ExpData.RIwvlns.indexOf( iwavl ); @@ -6079,7 +6094,7 @@ void US_ConvertGui::cancel_reference( void ) .arg( out_triples[ ii ] ) ); int kwavl = 99999; - for ( int jj = 0; jj < ExpData.RI_nwvlns; jj++ ) + for ( int jj = 0; jj < ExpData.RIwvlns.size(); jj++ ) { // Find index of nearest wavelength int jwavl = qAbs( ExpData.RIwvlns[ jj ] - iwavl ); @@ -9475,43 +9490,40 @@ void US_ConvertGui::PseudoCalcAvgMWL( void ) int ref_size = refData->xvalues.size(); int ccx = tripListx; int tripx = out_chandatx[ ccx ]; - nlambda = mwl_data.lambdas( exp_lambdas, tripListx ); ExpData.RI_nscans = refData->scanData.size(); -// ExpData.RI_nwvlns = all_wavelength_tripx.size(); DbgLv(1) << "PseCalcAvgMWL: ccx tripx nlambda" << ccx << tripx << nlambda; - QMap wvl_to_tripx; - for ( int wvx = 0; wvx < nlambda; wvx++ ) { - refData = outData[ tripx ]; - int wvl = refData->scanData.at(0).wavelength; - wvl_to_tripx[wvl] = tripx; - tripx++; - } + QVector unified_lambdas; + QVector unified_lambdas_tripx; + int counter = 0; + QVector argsort; + for ( int ii = 0; ii < outData.size(); ii++) { - // to make sure to take account half-wavelength lambda, each multiplies to 10 - // int wvl = qRound(outData.at(ii)->scanData.at(0).wavelength * 10); - int wvl = outData.at(ii)->scanData.at(0).wavelength; - if (wvl_to_tripx.contains(wvl)) { + int wvl = qRound( outData.at(ii)->scanData.first().wavelength ); + if (unified_lambdas.contains(wvl)) { continue; } - wvl_to_tripx[wvl] = ii; + unified_lambdas << wvl; + unified_lambdas_tripx << ii; + argsort << counter++; DbgLv(1) << "PseCalcAvgMWL: added_lambda tripx " << wvl << ii; } - ExpData.RI_nwvlns = wvl_to_tripx.size(); -DbgLv(1) << "PseCalcAvgMWL: tripx nlambda_i nlambda_f" << tripx << nlambda << wvl_to_tripx.size(); + ExpData.RI_nwvlns = unified_lambdas.size(); +DbgLv(1) << "PseCalcAvgMWL: tripx nlambda_i nlambda_f" << tripx << nlambda << unified_lambdas.size(); + std::sort( argsort.begin(), argsort.end(), [&unified_lambdas] (int a, int b) { + return unified_lambdas.at(a) < unified_lambdas.at(b); } ); // Loop to calculate reference data for each wavelength, // then apply it to all triples with that same wavelength. - foreach ( int iwavl, wvl_to_tripx.keys()) + for ( int ii = 0; ii < argsort.size(); ii++) { - tripx = wvl_to_tripx.value(iwavl); + int iwavl = unified_lambdas.at(argsort.at(ii)); + tripx = unified_lambdas_tripx.at(argsort.at(ii)); refData = outData[ tripx ]; - ref_size = refData->xvalues.size(); - int nscan = refData->scanData.size(); ri_prof.clear(); // Get the reference profile for the current wavelength - for ( int ss = 0; ss < nscan; ss++ ) + for ( int ss = 0; ss < ExpData.RI_nscans; ss++ ) { US_DataIO::Scan* scan = &refData->scanData[ ss ]; From 93316649875f323b60d0a5c034fa42f472ab0dec Mon Sep 17 00:00:00 2001 From: ehb54 Date: Thu, 21 Nov 2024 10:17:32 -0700 Subject: [PATCH 5/6] us_branch initlal commit --- admin/us_branch/us_branch.php | 219 +++++++++++++ admin/us_branch/utility.php | 567 ++++++++++++++++++++++++++++++++++ 2 files changed, 786 insertions(+) create mode 100755 admin/us_branch/us_branch.php create mode 100644 admin/us_branch/utility.php diff --git a/admin/us_branch/us_branch.php b/admin/us_branch/us_branch.php new file mode 100755 index 000000000..31cd7eabe --- /dev/null +++ b/admin/us_branch/us_branch.php @@ -0,0 +1,219 @@ +#!/usr/bin/php + += $this_level ) { + echo "${self}: $msg\n"; + } +} + +function timestamp( $msg = "" ) { + return date( "Y-m-d H:i:s " ) . $msg; +} + +function write_logld( $msg, $this_level = 0 ) { + global $logging_level; + global $self; + if ( $logging_level >= $this_level ) { + echo timestamp() . "${self}: $msg\n"; + } +} + +function db_obj_result( $db_handle, $query, $expectedMultiResult = false, $emptyok = false ) { + $result = mysqli_query( $db_handle, $query ); + + if ( !$result || ( is_object( $result ) && !$result->num_rows ) ) { + if ( $result ) { + # $result->free_result(); + } + if ( $emptyok ) { + return false; + } + write_logl( "db query failed : $query\ndb query error: " . mysqli_error($db_handle) . "\n" ); + if ( $result ) { + debug_json( "query result", $result ); + } + exit; + } + + if ( is_object( $result ) && $result->num_rows > 1 && !$expectedMultiResult ) { + write_logl( "WARNING: db query returned " . $result->num_rows . " rows : $query" ); + } + + if ( $expectedMultiResult ) { + return $result; + } else { + if ( is_object( $result ) ) { + return mysqli_fetch_object( $result ); + } else { + return $result; + } + } +} + +function debug_json( $msg, $json, $debuglevel = 0 ) { + global $debug; + global $STDERR; + if ( $debuglevel > 0 && $debug < $debuglevel ) { + return; + } + fwrite( $STDERR, "$msg\n" ); + fwrite( $STDERR, json_encode( $json, JSON_PRETTY_PRINT ) ); + fwrite( $STDERR, "\n" ); +} + +function echo_json( $msg, $json, $debuglevel = 0 ) { + echo "$msg\n"; + echo json_encode( $json, JSON_PRETTY_PRINT ); + echo "\n"; +} + +function run_cmd( $cmd, $die_if_exit = true, $array_result = false ) { + global $debug; + global $run_cmd_last_error; + + if ( isset( $debug ) && $debug ) { + echo "$cmd\n"; + } + exec( "$cmd 2>&1", $res, $run_cmd_last_error ); + if ( $die_if_exit && $run_cmd_last_error ) { + error_exit( "shell command '$cmd' returned result:\n" . implode( "\n", $res ) . "\nand with exit status '$run_cmd_last_error'" ); + } + if ( !$array_result ) { + return implode( "\n", $res ) . "\n"; + } + return $res; +} + +function error_exit( $msg ) { + global $STDERR; + fwrite( $STDERR, "$msg\nTerminating due to errors.\n" ); + exit(-1); +} + +function echoline( $str = "-", $count = 80, $print = true ) { + $out = ""; + for ( $i = 0; $i < $count; ++$i ) { + $out .= $str; + } + if ( $print ) { + echo "$out\n"; + } + return "$out\n"; +} + +function headerline( $msg, $str = "=", $count = 80, $print = true ) { + $out = + echoline( $str, $count, false ) + . "$msg\n" + . echoline( $str, $count, false ) + ; + if ( $print ) { + echo $out; + } + return $out; +} + +$warnings = ''; +$warnings_count = 0; +function flush_warnings( $msg = NULL ) { + global $warnings; + global $warnings_count; + if ( strlen( $warnings ) ) { + echo $warnings; + $warnings_count += count( explode( "\n", trim( $warnings ) ) ); + echoline(); + $warnings = ''; + return true; + } else { + if ( $msg ) { + echo "$msg\n"; + } + return false; + } +} + +function warnings_summary( $msg = NULL ) { + global $warnings_count; + return $warnings_count ? "Warnings generated $warnings_count\n" : ""; +} + +$errors = ''; +function flush_errors_exit() { + global $errors; + if ( strlen( $errors ) ) { + error_exit( $errors ); + } +} + +function get_yn_answer( $question, $quit_if_no = false ) { + global $STDERR; + echoline( '=' ); + do { + $answer = readline( "$question (y or n) : " ); + } while ( $answer != "y" && $answer != "n" ); + if ( $quit_if_no && $answer == "n" ) { + fwrite( $STDERR, "Terminated by user response.\n" ); + exit(-1); + } + return $answer == "y"; +} + +$util_backup_dir = ""; + +function backup_dir_init( $dir = "backup" ) { + global $util_backup_dir; + $util_backup_dir = "$dir-" . trim( run_cmd( 'date +"%Y%m%d%H%M%S"' ) ); + mkdir( $util_backup_dir ); + if ( !is_dir( $util_backup_dir ) ) { + error_exit( "Could not make backup directory $util_backup_dir" ); + } +} + +function backup_file( $filename ) { + global $util_backup_dir; + if ( !file_exists( $filename ) ) { + error_exit( "backup_file : $filename does not exist!" ); + } + if ( !strlen( $util_backup_dir ) ) { + backup_dir_init(); + } + run_cmd( "cp $filename $util_backup_dir" ); + echo "Original $filename backed up in to $util_backup_dir\n"; +} + +$newfile_dir = ""; + +function newfile_dir_init( $dir = "newfile" ) { + global $newfile_dir; + $newfile_dir = "$dir-" . trim( run_cmd( 'date +"%Y%m%d%H%M%S"' ) ); + mkdir( $newfile_dir ); + if ( !is_dir( $newfile_dir ) ) { + error_exit( "Could not make newfile directory $newfile_dir" ); + } + return $newfile_dir; +} + +function newfile_file( $filename, $contents ) { + global $newfile_dir; + if ( !strlen( $newfile_dir ) ) { + newfile_dir_init(); + } + $outfile = "$newfile_dir/$filename"; + if ( false === file_put_contents( $outfile, $contents ) ) { + error_exit( "Could not write $outfile" ); + } + echo "CREATED: New file $outfile\n"; + return $outfile; +} + +function is_admin( $must_be_root = true, $as_user = "" ) { + $user = posix_getpwuid(posix_geteuid())['name']; + if ( strlen( $as_user ) ) { + return $user == $as_user; + } + + if ( $user == 'root' ) { + return true; + } + if ( $must_be_root ) { + return false; + } + + $groupInfo = posix_getgrnam('wheel'); + if ($groupInfo === false) { + return false; + } + + return in_array( $user, $groupInfo['members'] ); +} + +$db_handle = NULL; + +function check_db( $sleep_seconds = 30 ) { + global $db_handle; + + while ( !mysqli_ping( $db_handle ) ) { + write_logld( "mysql server has gone away" ); + sleep( $sleep_seconds ); + write_logl( "attempting to reconnect" ); + open_db(); + if ( mysqli_ping( $db_handle ) ) { + write_logl( "reconnected - success" ); + } + } +} + +function open_db() { + global $db_handle; + global $dbhost; + global $user; + global $passwd; + $db_handle = mysqli_connect( $dbhost, $user, $passwd ); + if ( !$db_handle ) { + write_logl( "could not connect to mysql: $dbhost, $user. exiting\n" ); + exit(-1); + } +} + +function existing_dbs() { + global $db_handle; + if ( $db_handle === NULL ) { + open_db(); + } + $res = db_obj_result( $db_handle, "show databases like 'uslims3_%'", True ); + $existing_dbs = []; + while( $row = mysqli_fetch_array($res) ) { + $this_db = (string)$row[0]; + if ( $this_db != "uslims3_global" ) { + $existing_dbs[] = $this_db; + } + } + return $existing_dbs; +} + +function existing_stash_dbs() { + global $db_handle; + if ( $db_handle === NULL ) { + open_db(); + } + $res = db_obj_result( $db_handle, "show databases like 'stash_%'", true, true ); + $existing_dbs = []; + if ( $res ) { + while( $row = mysqli_fetch_array($res) ) { + $this_db = (string)$row[0]; + $existing_dbs[] = $this_db; + } + } + return $existing_dbs; +} + +function boolstr( $val, $truestr = "True", $falsestr = "" ) { + return $val ? $truestr : $falsestr; +} + +function tempdir( $dir = NULL, $prefix = NULL ) { + $template = "{$prefix}XXXXXX"; + if ( $dir && is_dir($dir) ) { + $tmpdir = "--tmpdir=$dir"; + } else { + $tmpdir = '--tmpdir=' . sys_get_temp_dir(); + } + return exec( "mktemp -d $tmpdir $template" ); +} + +function file_perms_must_be( $file, $least_restrictive = "600" ) { + $least_restrictive = octdec( $least_restrictive ); + if ( !file_exists( $file ) ) { + error_exit( "file permissions check: file '$file' does not exist" ); + } + $perms = fileperms( $file ) & octdec( "777" ); + $remainder = ( $perms | $least_restrictive ) - $least_restrictive; + if ( $remainder ) { + error_exit( sprintf( "Permissions on '$file' are too lenient, fix with:\nchmod %o $file", $least_restrictive ) ); + } + return; +} + +function get_slurm_cores( $cores = 4, $slurmconf = "/etc/slurm/slurm.conf" ) { + if ( !file_exists( $slurmconf ) ) { + return $cores; + } + $res = run_cmd( 'grep -e "^\s*NodeName\s*=\\s*localhost" ' . $slurmconf, false ); + preg_match( '/Procs=(\d+)\s/', $res, $matches ); + if ( count( $matches ) != 2 ) { + return $cores; + } + + return intval( $matches[1] * 2 ); +} + +/** + * Generates a Universally Unique IDentifier, version 4. + * + * RFC 4122 (http://www.ietf.org/rfc/rfc4122.txt) defines a special type of Globally + * Unique IDentifiers (GUID), as well as several methods for producing them. One + * such method, described in section 4.4, is based on truly random or pseudo-random + * number generators, and is therefore implementable in a language like PHP. + * + * We choose to produce pseudo-random numbers with the Mersenne Twister, and to always + * limit single generated numbers to 16 bits (ie. the decimal value 65535). That is + * because, even on 32-bit systems, PHP's RAND_MAX will often be the maximum *signed* + * value, with only the equivalent of 31 significant bits. Producing two 16-bit random + * numbers to make up a 32-bit one is less efficient, but guarantees that all 32 bits + * are random. + * + * The algorithm for version 4 UUIDs (ie. those based on random number generators) + * states that all 128 bits separated into the various fields (32 bits, 16 bits, 16 bits, + * 8 bits and 8 bits, 48 bits) should be random, except : (a) the version number should + * be the last 4 bits in the 3rd field, and (b) bits 6 and 7 of the 4th field should + * be 01. We try to conform to that definition as efficiently as possible, generating + * smaller values where possible, and minimizing the number of base conversions. + * + * @copyright Copyright (c) CFD Labs, 2006. This function may be used freely for + * any purpose ; it is distributed without any form of warranty whatsoever. + * @author David Holmes + * + * @return string A UUID, made up of 32 hex digits and 4 hyphens. + */ + +function uuid() { + + // The field names refer to RFC 4122 section 4.1.2 + + return sprintf('%04x%04x-%04x-%03x4-%04x-%04x%04x%04x', + mt_rand(0, 65535), mt_rand(0, 65535), // 32 bits for "time_low" + mt_rand(0, 65535), // 16 bits for "time_mid" + mt_rand(0, 4095), // 12 bits before the 0100 of (version) 4 for "time_hi_and_version" + bindec(substr_replace(sprintf('%016b', mt_rand(0, 65535)), '01', 6, 2)), + // 8 bits, the last two of which (positions 6 and 7) are 01, for "clk_seq_hi_res" + // (hence, the 2nd hex digit after the 3rd hyphen can only be 1, 5, 9 or d) + // 8 bits for "clk_seq_low" + mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535) // 48 bits for "node" + ); +} + +function is_locked( $php ) { + global $lock_dir; + if ( !isset( $lock_dir ) ) { + error_exit( "is_locked(): \$lock_dir is not set" ); + } + $lock_file = "$lock_dir/" . basename( $php ) . ".lock"; + $expected_cmdline = basename( $php ); + $isstale = false; + + if ( !file_exists($lock_file) ) { + # echo "file $lock_file does not exist\n"; + return false; + } + + if ( is_link($lock_file) ) { + # echo "is_link(" . $lock_file . ") true\n"; + if ( ( $link = readlink( $lock_file ) ) === FALSE ) { + $isstale = true; + # echo "is stale 1\n"; + } + } else { + $isstale = true; + # echo "is stale 2\n"; + } + # echo "tryLock() 2\n"; + + if ( !$isstale && is_dir( $link ) ) { + # make sure the cmdline exists & matches expected + $cmdline_file = $link . "/cmdline"; + echo "cmdline_file = $cmdline_file\n"; + if ( ($cmdline = file_get_contents( $cmdline_file )) === FALSE ) { + # echo "could not get contents of $cmdline_file\n"; + $isstale = true; + # echo "is stale 3\n"; + } else { + # remove nulls + $cmdline = str_replace("\0", "", $cmdline); + if ( strpos( $cmdline, $expected_cmdline ) === false ) { + # echo "unexpected contents of $cmdline_file\n"; + $isstale = true; + # echo "is stale 4 \n"; + } + } + } + # echo "tryLock() 3\n"; + + if (is_link($lock_file) && !is_dir($lock_file)) { + $isstale = true; + } + + return !$isstale; +} + +$dt_store_array = []; + +function dt_duration_minutes ( $datetime_start, $datetime_end ) { + return ($datetime_end->getTimestamp() - $datetime_start->getTimestamp()) / 60; +} + +function dt_now () { + return new DateTime( "now" ); +} + +function dt_store_now( $name ) { + global $dt_store_array; + $dt_store_array[ $name ] = dt_now(); +} + +function dt_store_get( $name ) { + global $dt_store_array; + if ( !array_key_exists( $name, $dt_store_array ) ) { + error_exit( "dt_store_get() : \$dt_array does not contain key '$name'" ); + } + return $dt_store_array[ $name ]; +} + +function dt_store_get_printable( $name ) { + $dt = dt_store_get( $name ); + return $dt->format( DATE_ATOM ); +} + +function dt_store_duration( $name_start, $name_end ) { + return sprintf( "%.2f", dt_duration_minutes( dt_store_get( $name_start ), dt_store_get( $name_end ) ) ); +} + +function dhms_from_minutes( $time ) { + $res = ''; + $days = floor( $time / (24 * 60) ); + $time -= $days * 24 * 60; + $hours = floor( $time / 60 ); + $time -= $hours * 60; + + if ( $days ) { + return sprintf( "%sd %sh %.2fm", $days, $hours, $time ); + } + if ( $hours ) { + return sprintf( "%sh %.2fm", $hours, $time ); + } + return sprintf( "%.2fm", $time ); +} + +function backup_rsync_email_headers() { + global $backup_host; + global $backup_user; + global $backup_email_address; + + $headers = + "From: backups $backup_host<$backup_user@$backup_host>\r\n" + . "Reply-To: $backup_email_address\r\n" + ; + + return $headers; +} + +function backup_rsync_failure( $msg ) { + global $backup_email_reports; + global $backup_email_address; + global $backup_host; + global $backup_logs; + global $date; + if ( !$backup_email_reports ) { + error_exit( $msg ); + } + $emaillog = "$backup_logs/summary-ERRORS-$date.txt"; + file_put_contents( $emaillog, $msg ); + if ( !mail( + $backup_email_address + ,"BACKUP ERRORS for $backup_host" + ,$msg + ,backup_rsync_email_headers() + ) + ) { + error_exit( $msg . "\nemail notification also failed" ); + } + error_exit( $msg ); +} + +function backup_rsync_run_cmd( $cmd, $die_if_exit = true ) { + global $debug; + if ( isset( $debug ) && $debug ) { + echo "$cmd\n"; + } + exec( "$cmd 2>&1", $res, $res_code ); + if ( $die_if_exit && $res_code ) { + backup_rsync_failure( "shell command '$cmd' returned result:\n" . implode( "\n", $res ) . "\nand with exit status '$res_code'" ); + } + return implode( "\n", $res ) . "\n"; +} + +function debug_echo ( $s, $debuglevel = 1 ) { + global $debug; + if ( !$debug || $debug < $debuglevel ) { + return; + } + echo "$s\n"; +} + +function fix_single_quote( $str, $rplc = "" ) { + return str_replace( "'", $rplc, $str ); +} + +## squash an object +## credit https://gist.github.com/woganmay/9a98dda059246bca664c + +function squash($array, $prefix = '') { + $flat = array(); + $sep = "."; + + if (!is_array($array)) $array = (array)$array; + + foreach($array as $key => $value) + { + $_key = ltrim($prefix.$sep.$key, "."); + + if (is_array($value) || is_object($value)) + { + // Iterate this one too + $flat = array_merge($flat, squash($value, $_key)); + } + else + { + $flat[$_key] = $value; + } + } + + return $flat; +} From 28db369ade10d36ff248ced336037abb95650274 Mon Sep 17 00:00:00 2001 From: ehb54 Date: Thu, 21 Nov 2024 11:26:41 -0600 Subject: [PATCH 6/6] Create README.md --- admin/us_branch/README.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 admin/us_branch/README.md diff --git a/admin/us_branch/README.md b/admin/us_branch/README.md new file mode 100644 index 000000000..c89f89f52 --- /dev/null +++ b/admin/us_branch/README.md @@ -0,0 +1,31 @@ +## Utility program for building and running ultrascan in $HOME/ultrascan3 + + * This allows users to build and test various branches or local mods to ultrascan3 + * Make sure to also install the home-gui-build modulefile (see admin/modulefiles) + +### typical install + * `$ cp -rp admin/us_branch /opt/` + +### run options +``` +/opt/us_branch/us_branch.php --help + +module is-avail ultrascan/home-gui-build +usage: /opt/us_branch/us_branch.php {options} + +utility checkout, build and run ultrascan3 from a specified branch +leverages module ultrascan/home-gui-build + +Options + +--help : print this information and exit + +--branch branchname : checkout branch +--pullrequest id : checkout from pull request +--build : build +--run : run +``` + +### notes + * if it for some reason fails, make sure to double check the `branchname` is correct + * remove or rename the ultrascan3 subdirectory in your home directory