. * * * User defined settings * ~~~~~~~~~~~~~~~~~~~~~ * If you wish to run OAFF on your own server, you will need to change the settings below. * You will also need to make sure that PHP is running with the sessions module installed and the HttpRequest extension available. * OAFF requires the PHP Entez Tools library. * OAFF can use a lot of memory, storage, and bandwidth -- make sure you keep an eye on these. * */ // How should OAFF identify itself to Entrez when requesting data? $ncbi_Tool = "OAFF"; /* * You will also need to edit 'lib/Variables.php' * * ********************************************************************************************************************************************/ error_reporting(E_ALL); ini_set('display_errors', '1'); require_once("lib/Variables.php"); session_start(); if (isset($_POST['NewSession'])) session_unset(); // Check if this is a new search and, if so, delete old session variables $PhpEntrezTool = new Oaff(); class Oaff { var $SearchTerm; var $CurResults; var $AuthorList; var $Stage; var $Translation; var $QueryKey; var $WebEnv; var $Count; var $Title; var $Html; var $StickyHtml; function Oaff() { if (!empty($_SESSION['SearchTerm'])) $this->SearchTerm = $_SESSION['SearchTerm']; if (!empty($_SESSION['PostData'])) $this->PostData = $_SESSION['PostData']; if (!empty($_SESSION['CurResults'])) $this->CurResults = $_SESSION['CurResults']; if (!empty($_SESSION['AuthorList'])) $this->AuthorList = $_SESSION['AuthorList']; if (!empty($_SESSION['Stage'])) $this->Stage = $_SESSION['Stage']; if (!empty($_SESSION['Count'])) $this->Count = $_SESSION['Count']; if (!empty($_SESSION['Translation'])) $this->Translation = $_SESSION['Translation']; if (!empty($_SESSION['QueryKey'])) $this->QueryKey = $_SESSION['QueryKey']; if (!empty($_SESSION['WebEnv'])) $this->WebEnv = $_SESSION['WebEnv']; if (!empty($_SESSION['StickyHtml'])) $this->StickyHtml = $_SESSION['StickyHtml']; else $this->StickyHtml = ""; $this->Html = ""; if (empty($this->Stage)) { $_SESSION['began'] = microtime(true); $this->Stage = array("search", 1); if (empty($_POST['SearchTerm'])) { $this->Html .= "

Input error. Check the search box!

\n"; $this->OutputHtml(); exit; } $this->SearchTerm = $_POST['SearchTerm']; $this->PostData = array( "MinOa" => $_POST['MinOA'], "MinAl" => $_POST['MinAl'], ); $this->PmcIds(); if ($this->CheckCache() == 1) { $this->CurResults = $this->GetCacheResults(); $_SESSION['ToFilter'] = count($this->CurResults); $this->Stage = array("filters", 0); } else $this->PmcExtractAuthors(); } elseif ($this->Stage[0] == "search") $this->PmcExtractAuthors(); if ($this->Stage[0] == "filters") $this->PmcFilters(); if (!empty($_GET['order'])) $this->ReorderOutput($_GET['order']); $this->PrintResults(); } function PmcIds( $Force = false ) { require_once("lib/eSearch.php"); try { $eSearch = new eSearch( "pmc", $this->SearchTerm, "1900/01/01", date('Y/m/01') ); if ($Force) { // If run with $Force, delete old cache first. $eSearch->MakeCacheName(); $eSearch->DeleteCache(); } $eSearch->Run(2); $this->Translation = $eSearch->Translation; $this->QueryKey = $eSearch->QueryKey; $this->WebEnv = $eSearch->WebEnv; $this->Count = $eSearch->Count; if (empty($eSearch->Count)) { $this->Title = "OAFF - Search complete"; $this->Html .= "

Sorry, PubMed has no items matching your search for " . $this->SearchTerm . ". Check your spelling, or try an older date cutoff.

\n"; $this->OutputHtml(); exit; } } catch (Exception $e) { $this->Html .= "

Warning: caught an exception when trying to retreive the XML data from PubMed. I am going to reload the page and hope that the problem goes away. The error given was: " . $e->getMessage() . "

\n"; $eSearch->DeleteCache(); $this->SaveReload(); exit; } } function PmcExtractAuthors() { Global $ncbi_RetMax; require_once("lib/eSummary.php"); try { $eSummary = new eSummary('pmc', $this->QueryKey, $this->WebEnv, $this->Stage[1], $ncbi_RetMax); $eSummary->Identifier = $this->Translation; $eSummary->Run(); } catch (Exception $e) { $this->Html .= "

Warning: caught an exception when trying to retreive the XML data from PubMed. I am going to reload the page and hope that the problem goes away. The error given was: " . $e->getMessage() . "

\n"; $this->PmcIds(true); $this->SaveReload(); exit; } $lines = explode("\n", $eSummary->Xml); // Extract all of the authors from the XML string unset($eSummary); // destroy eSummary so as to save on memory foreach ($lines as $line) { $line = trim($line); if (substr($line, 0, 34) == "") { $AuList = explode(",", substr($line, 34, -7)); foreach ($AuList as $NewAuthor) { $NewAuthor = trim($NewAuthor); if (!empty($this->CurResults[$NewAuthor])) $this->CurResults[$NewAuthor] += 1; else $this->CurResults[$NewAuthor] = 1; } } } $this->Stage[1] += $ncbi_RetMax; if ($this->Stage[1] > $this->Count) { $this->SaveAuthors(); $this->Stage = array("filters", 0); $_SESSION['ToFilter'] = count($this->CurResults); } $this->SaveReload(); exit; } function PmcFilters() { if (empty($this->CurResults)) { $this->Html .= "

Error: empty results in Oaff->PmcFilters()

\n"; $this->OutputHtml(); exit; } $i = 0; foreach ($this->CurResults as $Author => $Count) { // Get count for all open-access pubs $AuSe = $Author . " (" . $this->SearchTerm . ")"; $Oa = $this->PmcFilterPubs('pmc', $Author); if ($Oa < $this->PostData['MinOa']) { unset($this->CurResults[$Author]); $i += 1; $_SESSION['Filtered'] += 1; continue; } $Al = $this->PmcFilterPubs('pubmed', $Author); if ($Al < $this->PostData['MinAl']) { unset($this->CurResults[$Author]); $i += 1; $_SESSION['Filtered'] += 1; continue; } $this->AuthorList[$Author] = array( "OaSe" => $Count, "Oa" => $Oa, "Al" => $Al, ); $this->AuthorList[$Author]['AvAl'] = ($this->AuthorList[$Author]['Oa'] / $this->AuthorList[$Author]['Al']) * 100; unset($this->CurResults[$Author]); $i += 1; $_SESSION['Filtered'] += 1; if ($i > 500) if (!empty($this->CurResults)) $this->SaveReload(); } $this->ReorderOutput("AvAl"); $this->PrintResults(); } function PmcFilterPubs($DB, $Author) { require_once("lib/eSearch.php"); try { $eSearch = new eSearch( $DB, $Author, "1900/01/01", date('Y/m/01'), 20, "count" ); $eSearch->Run(2); if (empty($eSearch->Count)) $this->StickyHtml .= "

Error: empy count for $DB > $Author.

\n"; return $eSearch->Count; } catch (Exception $e) { $this->Html .= "

Warning: caught an exception when trying to retreive the XML data from PubMed. I am going to reload the page and hope that the problem goes away. The error given was: " . $e->getMessage() . "

\n"; $this->SaveReload(); exit; } } function ReorderOutput($order) { foreach ($this->AuthorList as $Author => $Items) { foreach ($Items as $Term => $Count) { $temp[$Term][$Author] = $Count; } } arsort($temp[$order]); foreach ($temp[$order] as $Author => $Count) { $temp2[$Author][$order] = $Count; } foreach ($temp as $Term => $Items) { foreach ($Items as $Author => $Count) { $temp2[$Author][$Term] = $Count; } } $this->AuthorList = $temp2; return true; } /******************************************************************************************************************************************************************* FILE/CACHE FUNCTIONS *******************************************************************************************************************************************************************/ /*************************************************************************************************************************************** * Function: GetCacheName ( ) * - Makes the cache filename */ function GetCacheName() { Global $ncbi_CachePath; $f = $ncbi_CachePath . "Oaff/" . md5($this->Translation) . ".txt"; // Build the filename from the full path and md5 scrambled translation return $f; } /*************************************************************************************************************************************** * Function GetCacheAttribs * - Gets everything above the [Results] section from the cache file */ function GetCacheAttribs() { $f = $this->GetCacheName(); if (!file_exists($f)) { $this->StickyHtml .= "

Warning: script ran GetCacheAttribs() on a non-existent cache.

\n"; return 0; // Return 0 for files which do not exist } $x = file_get_contents($f); // Extract from the file $x = str_replace("\r\n", "\n", $x); // This is a (temp?) fix for processing *nix generated author lists on windows servers $a = explode("[Results]\n", $x); $a = explode("\n", $a[0]); foreach ($a as $k => $v) { if (empty($v)) continue; $v = explode("=", $v); $r[$v[0]] = $v[1]; } return $r; } /*************************************************************************************************************************************** * Function GetCacheResults * - Extracts the author list from a cache file and returns it as an array */ function GetCacheResults() { $f = $this->GetCacheName(); $x = file_get_contents($f); // Extract from the file $x = str_replace("\r\n", "\n", $x); // This is a (temp?) fix for processing *nix generated author lists on windows servers $a = explode("[Results]\n", $x); $a = explode("\n", $a[1]); foreach ($a as $k => $v) { if (empty($v)) continue; $v = explode("=", $v); $r[$v[0]] = $v[1]; } return $r; } /*************************************************************************************************************************************** * Function CheckCache * - checks to see if the cache file exists, and if so, if it is current */ function CheckCache() { $f = $this->GetCacheName(); if (!file_exists($f)) return 0; // Return 0 for files which do not exist $a = $this->GetCacheAttribs(); if ((date('Y', $a['Updated']) == date('Y')) and (date('m', $a['Updated']) == date('m'))) return 1; // Return 1 for files which are up-to-date return 2; // Return 2 for files which need updating } /**************************************************************************************************************************************** * Function: SaveAuthors * - I wanted to use an XML layout for the saved authors list, but that considerably raises the amount of memory required (e.g. to get * the array back out of the xml file). Therefore, we have to put up with a cheap and dirty solution * - In v0.4 this had a "TempSave" option, now moved to a dedicated function */ function SaveAuthors() { $cutoff = 1; // If there are too many results, we can ignore all who have only one item $total = count($this->CurResults); // for the sake of performance if ($total > 250000) $cutoff = 2; // (the original cutoff was based on results for the search - i.e. this->PostData[Searches][n][Count]) foreach ($this->CurResults as $author => $count) { if ($count >= $cutoff) $a[] = $author . "=" . $count; } if ($this->CheckCache() and ($o = $this->GetCacheAttribs())) { // Find out when the cache was first made if (!empty($o['Created'])) $Created = $o['Created']; // This if/else is to cope with pre v0.5 cache files which do not have the created else $Created = $o['Updated']; // data - when those cache files have been updated, this can be removed. } else $Created = time(); $t = "SearchTerm=" . $this->SearchTerm . "\nQueryTranslation=" . $this->Translation ."\nCreated=" . $Created ."\nUpdated=" . time() . "\nCount=" . $this->Count . "\nAuCount=" . count($this->CurResults) . "\n\n[Results]\n" . implode("\n", $a); $c = $this->GetCacheName(); // Save the cache to the file if (file_exists($c)) unlink($c); $f = fopen($c, 'w+'); fwrite($f, $t); fclose($f); unset($a, $t, $f, $o); if (!empty($_SESSION['Cleanup'])) foreach ($_SESSION['Cleanup'] as $f) { if (file_exists($f)) unlink($f); } // At this point we can delete the redundant XML files return true; } /******************************************************************************************************************************************************************* HTML FUNCTIONS *******************************************************************************************************************************************************************/ /******************************************************************************************************************************************** * Function: OutputHtml( Reload ) * Formats the page as HTML */ function OutputHtml($Reload = false) { $Title = $this->Title; $Html = $this->StickyHtml . $this->Html; if ($Reload) $Reload = "\n"; else $Reload = ""; $Time = round((microtime(true) - $_SESSION['began']), 2); // Calculate the time elapsed echo << $Title $Reload

OAFFbeta: the open-access friend finder

$Html

... time elapsed: $Time seconds.

END; exit; } /******************************************************************************************************************************************** * Function: SaveReload() * Saves variables and reloads the page to move on to the next stage */ function SaveReload() { $_SESSION['Stage'] = $this->Stage; $_SESSION['SearchTerm'] = $this->SearchTerm; $_SESSION['PostData'] = $this->PostData; $_SESSION['StickyHtml'] = $this->StickyHtml; if (isset($this->WebEnv)) $_SESSION['WebEnv'] = $this->WebEnv; if (isset($this->QueryKey)) $_SESSION['QueryKey'] = $this->QueryKey; if (isset($this->AuthorList)) $_SESSION['AuthorList'] = $this->AuthorList; if (isset($this->CurResults)) $_SESSION['CurResults'] = $this->CurResults; if (isset($this->Count)) $_SESSION['Count'] = $this->Count; if (isset($this->Translation)) $_SESSION['Translation'] = $this->Translation; if ($this->Stage[0] == "search") { $width = ($this->Stage[1] / $this->Count) * 600; $pc = round(($width / 6), 2); $width = round($width); $width2 = 600 - $width; $this->Html .= "

\n

PMC Search: " . $pc . "% (" . $this->Stage[1] . " / " . $this->Count . ")

\n"; $this->Html .= "

\n

Post-search filters: 0%

\n"; } elseif ($this->Stage[0] == "filters") { $this->Html .= "

\n

PMC Search: 100% (" . $this->Count . " / " . $this->Count . ")

\n"; if (isset($_SESSION['Filtered']) and isset($_SESSION['ToFilter'])) { $width = ($_SESSION['Filtered'] / $_SESSION['ToFilter']) * 600; $pc = round(($width / 6), 2); $width = round($width); $width2 = 600 - $width; $this->Html .= "

\n

Applying limits and filters: " . $pc . "%

\n"; } else $this->Html .= "

\n

Post-search filters: 0%

\n"; } $this->Title = "OAFF: Processing searches..."; $this->OutputHtml(true); } /******************************************************************************************************************************************** * Function: PrintResults() * */ function PrintResults() { $this->Html .= "
\n\n"; $this->Html .= "\n"; $this->Html .= "\n"; $this->Html .= "\n"; $this->Html .= "\n"; $this->Html .= "\n"; $this->Html .= "\n"; // Print the column headers $this->Html .= "\n"; $this->Html .= "\n"; $this->Html .= "\n"; $this->Html .= "\n"; $this->Html .= "\n"; $this->Html .= "\n"; foreach ($this->AuthorList as $Author => $Lists) { $this->Html .= "\n\n"; $this->Html .= "\n"; $this->Html .= "\n"; $this->Html .= "\n"; $this->Html .= "\n"; $this->Html .= "\n\n"; } $this->Html .= "
 " . $this->SearchTerm . "All publications
AuthorOpen-access Total Open-access Total Avg (%)
" . $Author . "SearchTerm . ")\">" . $Lists['OaSe'] . "SearchTerm . ")\">" . $Lists['AlSe'] . "" . $Lists['Oa'] . "" . $Lists['Al'] . "" . round($Lists['AvAl'], 2) . "
\n"; } } ?>