2
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
* ImgIndex Class definition
10
* @author Jeff Stys <jeff.stys@nasa.gov>
11
* @author Keith Hughitt <keith.hughitt@nasa.gov>
12
* @author Patrick Schmiedel <patrick.schmiedel@gmx.net>
13
* @license http://www.mozilla.org/MPL/MPL-1.1.html Mozilla Public License 1.1
14
* @link http://launchpad.net/helioviewer.org
17
* Provides methods for interacting with a JPEG 2000 archive.
20
* @package Helioviewer
21
* @author Jeff Stys <jeff.stys@nasa.gov>
22
* @author Keith Hughitt <keith.hughitt@nasa.gov>
23
* @author Patrick Schmiedel <patrick.schmiedel@gmx.net>
24
* @license http://www.mozilla.org/MPL/MPL-1.1.html Mozilla Public License 1.1
25
* @link http://launchpad.net/helioviewer.org
27
class Database_ImgIndex {
29
private $_dbConnection;
36
public function __construct() {
37
$this->_dbConnection = false;
41
* Create a connection to the database if one has not already been made.
45
private function _dbConnect() {
46
if ( $this->_dbConnection === false ) {
47
include_once HV_ROOT_DIR.'/src/php/Database/DbConnection.php';
48
$this->_dbConnection = new Database_DbConnection();
53
* Insert a new screenshot into the `screenshots` table.
55
* @return int Identifier in the `screenshots` table
57
public function insertScreenshot($date, $imageScale, $roi, $watermark,
58
$layers, $bitmask, $events, $eventsLabels, $scale, $scaleType,
59
$scaleX, $scaleY, $numLayers) {
61
include_once HV_ROOT_DIR.'/src/php/Helper/DateTimeConversions.php';
66
"INSERT INTO screenshots "
69
. "timestamp " . " = NULL, "
70
. "observationDate " . " ='%s', "
71
. "imageScale " . " = %f, "
72
. "regionOfInterest " . " = PolygonFromText('%s'), "
73
. "watermark " . " = %b, "
74
. "dataSourceString " . " ='%s', "
75
. "dataSourceBitMask " . " = %d, "
76
. "eventSourceString " . " ='%s', "
77
. "eventsLabels " . " = %b, "
78
. "scale " . " = %b, "
79
. "scaleType " . " ='%s', "
80
. "scaleX " . " = %f, "
81
. "scaleY " . " = %f, "
82
. "numLayers " . " = %d;",
83
$this->_dbConnection->link->real_escape_string(
84
isoDateToMySQL($date) ),
86
$this->_dbConnection->link->real_escape_string(
89
$this->_dbConnection->link->real_escape_string(
91
bindec($this->_dbConnection->link->real_escape_string(
93
$this->_dbConnection->link->real_escape_string(
97
$this->_dbConnection->link->real_escape_string(
104
$result = $this->_dbConnection->query($sql);
106
catch (Exception $e) {
110
return $this->_dbConnection->getInsertId();
114
* Fetch metadata about a movie from the `movies` table.
116
* @param $movieId int Identifier in the `movies` table
118
* @return Array represesenting a row in the `movies` table
120
public function getMovieInformation($movieId) {
124
"SELECT *, AsText(regionOfInterest) AS roi "
127
. "movieFormats ON movies.id = movieFormats.movieId "
129
. "movies.id = %d AND "
130
. "movieFormats.format = 'mp4' "
135
$result = $this->_dbConnection->query($sql);
137
catch (Exception $e) {
141
return $result->fetch_array(MYSQLI_ASSOC);
145
* Update a row in the `movies` table with metadata describing the
146
* generated movie's attributes.
148
* @return boolean true or false
150
public function storeMovieProperties($movieId, $startDate, $endDate,
151
$numFrames, $frameRate, $length, $width, $height) {
158
. "startDate " . " ='%s', "
159
. "endDate " . " ='%s', "
160
. "numFrames " . " = %d, "
161
. "frameRate " . " = %f, "
162
. "movieLength " . " = %f, "
163
. "width " . " = %d, "
164
. "height " . " = %d "
165
. "WHERE id " . " = %d "
167
$this->_dbConnection->link->real_escape_string(
169
$this->_dbConnection->link->real_escape_string(
179
$result = $this->_dbConnection->query($sql);
181
catch (Exception $e) {
189
* Update a row in the `movies` table with processesing start and end times
191
* @param $movieId int Identifier in the `movies` table
192
* @param $buildTimeStart string Movie build start time
193
* @param $buildTimeEnd string Movie build end time
195
* @return Boolean true or false
197
public function finishedBuildingMovieFrames($movieId, $buildTimeStart,
205
. "buildTimeStart " . " ='%s', "
206
. "buildTimeEnd= " . " ='%s' "
207
. "WHERE id " . " = %d "
209
$this->_dbConnection->link->real_escape_string(
211
$this->_dbConnection->link->real_escape_string(
216
$result = $this->_dbConnection->query($sql);
218
catch (Exception $e) {
226
* Mark a movie as "processing" in the `movieFormats` table.
228
* @param $movieId int Identifier in the `movies` table
229
* @param $format string Movie format being processed
231
* @return Boolean true or false
233
public function markMovieAsProcessing($movieId, $format) {
237
"UPDATE movieFormats "
238
. "SET status = 1 " // 1 = processing
240
. "movieId " . " = %d AND "
241
. "format " . " ='%s' "
244
$this->_dbConnection->link->real_escape_string(
248
$result = $this->_dbConnection->query($sql);
250
catch (Exception $e) {
258
* Mark a movie as "finished" in the `movieFormats` table.
260
* @param $movieId int Identifier in the `movies` table
261
* @param $format string Movie format being processed
262
* @param $procTime int Number of seconds it took to encode the movie
264
* @return Boolean true or false
266
public function markMovieAsFinished($movieId, $format, $procTime) {
270
"UPDATE movieFormats "
272
. "status " . " = 2, " // 2 = finished
273
. "procTime " . " = %d "
275
. "movieId " . " = %d AND "
276
. "format " . " ='%s' "
280
$this->_dbConnection->link->real_escape_string(
284
$result = $this->_dbConnection->query($sql);
286
catch (Exception $e) {
294
* Mark a movie as "invalid" in the `movieFormats` table.
296
* @param int $movieId Identifier in the `movies` table
298
* @return Boolean true or false
300
public function markMovieAsInvalid($movieId) {
304
"UPDATE movieFormats "
306
. "status " . " = 3, " // 3 = invalid
307
. "procTime " . " = NULL "
309
. "movieId " . " = %d "
314
$result = $this->_dbConnection->query($sql);
316
catch (Exception $e) {
324
* Fetch metadata about a screenshot from the `screenshots` table.
326
* @param int $screenshotId Identifier in the `screenshots` table
328
* @return Array represesenting a row in the `screenshots` table
330
public function getScreenshot($screenshotId) {
335
. "FROM screenshots "
341
$result = $this->_dbConnection->query($sql);
343
catch (Exception $e) {
347
return $result->fetch_array(MYSQLI_ASSOC);
351
* Fetch metadata about an image from the `data` and `datasources` tables
352
* as well as the XML box of the JP2 image file. Not for use with
353
* non-image data sources.
355
* @param int $dataId The image's identifier in the `data` table
357
* @return array Metadata related to the requested image.
359
public function getImageInformation($dataId) {
363
"SELECT * FROM data WHERE id = %d LIMIT 1;",
367
$result = $this->_dbConnection->query($sql);
369
catch (Exception $e) {
373
$image = $result->fetch_array(MYSQLI_ASSOC);
375
// Fetch metadata from JP2 XML header
376
$image_filepath = HV_JP2_DIR.$image['filepath'].'/'.$image['filename'];
377
$xmlBox = $this->extractJP2MetaInfo($image_filepath);
379
// Fetch metadata from the `datasources` table
380
$datasource = $this->getDatasourceInformationFromSourceId(
383
return array_merge($image, $xmlBox, $datasource);
387
* Find available data that is closest to the requested time and
388
* return its metadata from the database and xmlBox (if applicable).
390
* @param string $date A UTC date string of the form "2003-10-05T00:00:00Z"
391
* @param int $sourceId The data source's identifier in the database
393
* @return array Metadata related to the closest image or other data type.
395
public function getClosestData($date, $sourceId) {
396
$data = $this->getDataFromDatabase($date, $sourceId);
397
$filename = HV_JP2_DIR.$data['filepath'].'/'.$data['filename'];
399
if ( stripos($data['filename'], '.jp2') !== false ) {
400
$xmlBox = $this->extractJP2MetaInfo($filename);
401
return array_merge($data, $xmlBox);
407
* Query the database for data that is closest to the requested time.
409
* @param string $date A UTC date string of the form "2003-10-05T00:00:00Z"
410
* @param int $sourceId The data source's identifier in the database
412
* @return array Associative array containing values from
413
* the `datasources` table.
415
public function getDataFromDatabase($date, $sourceId) {
416
include_once HV_ROOT_DIR.'/src/php/Helper/DateTimeConversions.php';
420
$datestr = isoDateToMySQL($date);
424
. "id, filepath, filename, date "
427
. "sourceId " . " = %d AND "
428
. "date " . " <'%s' "
429
. "ORDER BY date DESC "
433
. "id, filepath, filename, date "
436
. "sourceId " . " = %d AND "
437
. "date " . ">='%s' "
438
. "ORDER BY date ASC "
441
. "ABS(TIMESTAMPDIFF(MICROSECOND, date, '%s') "
444
$this->_dbConnection->link->real_escape_string(
447
$this->_dbConnection->link->real_escape_string(
449
$this->_dbConnection->link->real_escape_string(
453
$result = $this->_dbConnection->query($sql);
455
catch (Exception $e) {
459
$data = $result->fetch_array(MYSQLI_ASSOC);
460
if ( $data === null ) {
461
$source = $this->_getDataSourceName($sourceId);
462
throw new Exception("No data of the requested type ("
463
.$source.") are currently available.", 10);
470
* Return the closest match from the `data` table whose time is on
471
* or before the specified time.
473
* @param string $date UTC date string like "2003-10-05T00:00:00Z"
474
* @param int $sourceId The data source identifier in the database
476
* @return array Array containing 1 row from the `data` table
478
public function getClosestDataBeforeDate($date, $sourceId) {
479
include_once HV_ROOT_DIR.'/src/php/Helper/DateTimeConversions.php';
483
$datestr = isoDateToMySQL($date);
486
"SELECT filepath, filename, date "
489
. "sourceId " . " = %d AND "
490
. "date " . "<='%s' "
491
. "ORDER BY date DESC "
494
$this->_dbConnection->link->real_escape_string(
498
$result = $this->_dbConnection->query($sql);
500
catch (Exception $e) {
504
$data = $result->fetch_array(MYSQLI_ASSOC);
505
if ( $data === null ) {
506
$source = $this->_getDataSourceName($sourceId);
507
throw new Exception( 'No '.$source.' data is available '
508
. 'on or before '.$date.'.', 11);
515
* Return the closest match from the `data` table whose time is on
516
* or after the specified time.
518
* @param string $date UTC date string like "2003-10-05T00:00:00Z"
519
* @param int $sourceId The data source identifier in the database
521
* @return array Array containing 1 row from the `data` table
523
public function getClosestDataAfterDate($date, $sourceId) {
524
include_once HV_ROOT_DIR.'/src/php/Helper/DateTimeConversions.php';
528
$datestr = isoDateToMySQL($date);
531
"SELECT filepath, filename, date "
534
. "sourceId " . " = %d AND "
535
. "date " . ">='%s' "
536
. "ORDER BY date ASC "
539
$this->_dbConnection->link->real_escape_string(
543
$result = $this->_dbConnection->query($sql);
545
catch (Exception $e) {
549
$data = $result->fetch_array(MYSQLI_ASSOC);
550
if ( $data === null ) {
551
$source = $this->_getDataSourceName($sourceId);
552
throw new Exception( 'No '.$source.' data is available '
553
. 'on or after '.$date.'.', 11);
560
* Get the human-readable name associated with the specified source id.
562
* @param int $sourceId The data source identifier in the database
564
* @return string Name of the data source associated with specified id
566
private function _getDataSourceName($sourceId) {
570
"SELECT name FROM datasources WHERE id = %d LIMIT 1;",
574
$result = $this->_dbConnection->query($sql);
576
catch (Exception $e) {
580
$datasource = $result->fetch_array(MYSQLI_ASSOC);
581
return $datasource['name'];
585
* Return the number `data` table rows matching a source and time range
587
* @param datetime $start Query start time
588
* @param datetime $end Query end time
589
* @param int $sourceId The data source identifier in the database
591
* @return int The number of `data` rows matching a source and time range
593
public function getDataCount($start, $end, $sourceId) {
594
include_once HV_ROOT_DIR.'/src/php/Helper/DateTimeConversions.php';
598
$startDate = isoDateToMySQL($start);
599
$endDate = isoDateToMySQL($end);
602
"SELECT COUNT(id) as count "
605
. "sourceId " . " = %d AND "
606
. "date BETWEEN '%s' AND '%s' "
609
$this->_dbConnection->link->real_escape_string(
611
$this->_dbConnection->link->real_escape_string(
615
$result = $this->_dbConnection->query($sql);
617
catch (Exception $e) {
621
$data = $result->fetch_array(MYSQLI_ASSOC);
622
return $data['count'];
626
* Return an array of data from a given data source within the specified
629
* @param datetime $start Query start time
630
* @param datetime $end Query end time
631
* @param int $sourceId The data source identifier in the database
633
* @return array Array containing matched rows from the `data` table
635
public function getDataRange($start, $end, $sourceId) {
636
include_once HV_ROOT_DIR.'/src/php/Helper/DateTimeConversions.php';
641
$startDate = isoDateToMySQL($start);
642
$endDate = isoDateToMySQL($end);
648
. "sourceId = %d AND "
649
. "date BETWEEN '%s' AND '%s' "
650
. "ORDER BY date ASC;",
652
$this->_dbConnection->link->real_escape_string(
654
$this->_dbConnection->link->real_escape_string(
658
$result = $this->_dbConnection->query($sql);
660
catch (Exception $e) {
664
$result_array = Array();
665
while ( $row = $result->fetch_array(MYSQLI_ASSOC) ) {
666
array_push($data, $row);
673
* Extract metadata from JP2 image file's XML header
675
* @param string $image_filepath Full path to JP2 image file
677
* @return array A subset of the information stored in the jp2 header
679
public function extractJP2MetaInfo($image_filepath) {
681
include_once HV_ROOT_DIR.'/src/php/Image/JPEG2000/JP2ImageXMLBox.php';
684
$xmlBox = new Image_JPEG2000_JP2ImageXMLBox($image_filepath);
686
$dimensions = $xmlBox->getImageDimensions();
687
$refPixel = $xmlBox->getRefPixelCoords();
688
$imageScale = (float) $xmlBox->getImagePlateScale();
689
$dsun = (float) $xmlBox->getDSun();
690
$sunCenterOffsetParams = $xmlBox->getSunCenterOffsetParams();
691
$layeringOrder = $xmlBox->getLayeringOrder();
693
// Normalize image scale
694
$imageScale = $imageScale * ($dsun / HV_CONSTANT_AU);
697
"scale" => $imageScale,
698
"width" => (int) $dimensions[0],
699
"height" => (int) $dimensions[1],
700
"refPixelX" => (float) $refPixel[0],
701
"refPixelY" => (float) $refPixel[1],
702
"sunCenterOffsetParams" => $sunCenterOffsetParams,
703
"layeringOrder" => $layeringOrder
706
catch (Exception $e) {
708
sprintf("Unable to process XML Header for %s: %s",
718
* Fetch datasource properties from the database.
720
* @param int $sourceId Identifier in the `datasources` and
721
* `datasource_property` tables
723
* @return Array Datasource metadata
725
public function getDatasourceInformationFromSourceId($sourceId) {
732
. "ds.name as 'nickname', "
733
. "ds.layeringOrder "
735
. "datasource_property dp "
737
. "datasources ds ON dp.sourceId = ds.id "
740
. "ORDER BY uiOrder ASC;",
744
$result = $this->_dbConnection->query($sql);
746
catch (Exception $e) {
751
$result_array = Array();
752
$result_array['uiLabels'] = Array();
753
while ( $row = $result->fetch_array(MYSQLI_ASSOC) ) {
754
$result_array['uiLabels'][] = Array('label'=>$row['label'], 'name'=>$row['name']);
755
$nickname = $row['nickname'];
756
$layeringOrder = $row['layeringOrder'];
759
$result_array['name'] = $nickname;
760
$result_array['layeringOrder'] = $layeringOrder;
762
return $result_array;
766
* Return `datasource` id, name, layeringOrder for the matched labels
768
* @param array Array of `datasource_property`.name in uiOrder order
770
* @return array Array of `datasource` id, name, layeringOrder
772
public function getDatasourceInformationFromNames($property_array) {
775
$letters = array('a','b','c','d','e');
776
$select_clause = array('ds.id', 'ds.name', 'ds.layeringOrder');
777
$from_clause = array();
778
$where_clause = array();
781
foreach ($property_array as $i=>$property) {
783
$property = $this->_dbConnection->link->real_escape_string(
786
$select_clause[] = $letters[$i].'.label AS '.$letters[$i].'_label';
787
$from_clause[] = 'datasource_property '.$letters[$i];
789
$where_clause[] = 'ds.id=a.sourceId';
790
$where_clause[] = 'a.sourceId='.$letters[$i].'.sourceId';
792
$where_clause[] = $letters[$i].'.name="'.$property.'"';
793
$where_clause[] = $letters[$i].'.uiOrder='.++$i;
795
$sql = 'SELECT ' . implode(', ', $select_clause) . ' ';
796
$sql .= 'FROM datasources ds, ' . implode(', ', $from_clause);
797
$sql .= ' WHERE ' . implode(' AND ', $where_clause);
800
$result = $this->_dbConnection->query($sql);
802
catch (Exception $e) {
806
$row = $result->fetch_array(MYSQLI_ASSOC);
808
$result_array = Array();
809
$result_array['id'] = $row['id'];
810
$result_array['name'] = $row['name'];
811
$result_array['layeringOrder'] = $row['layeringOrder'];
812
$result_array['uiLabels'] = Array();
814
foreach ($property_array as $i=>$property) {
815
$result_array['uiLabels'][] = Array(
816
'label' => $row[$letters[$i].'_label'],
817
'name' => $property);
820
return $result_array;
824
* Return the UI labels for the matched `datasource_property` names
826
* @param array Array of `datasource_property`.name in uiOrder order
828
* @return array Array of `datasource_property` label in uiOrder order
830
public function getDataSourceLabels($property_array) {
833
$letters = array('a','b','c','d','e');
834
$select_clause = array();
835
$join_clause = array();
836
$where_clause = array();
838
foreach ($property_array as $i=>$property) {
840
$property = $this->_dbConnection->link->real_escape_string(
843
$select_clause[] = $letters[$i].'.label as "'.$i.'"';
846
$join_clause[] = 'LEFT JOIN datasource_property '.$letters[$i];
847
$join_clause[] = 'ON a.sourceId = '.$letters[$i].'.sourceId';
850
$where_clause[] = $letters[$i].'.name="'.$property.'"';
851
$where_clause[] = $letters[$i].'.uiOrder='.++$i;
854
$sql = 'SELECT ' . implode(', ', $select_clause);
855
$sql .= ' FROM datasource_property a ';
856
$sql .= implode(' ', $join_clause);
857
$sql .= ' WHERE ' . implode(' AND ', $where_clause);
860
$result = $this->_dbConnection->query($sql);
862
catch (Exception $e) {
866
$row = $result->fetch_array();
867
foreach ($property_array as $i=>$property) {
868
$return_array[$row[$i]] = $property;
871
return $return_array;
876
* Return `datasource` identifier for the matched labels
878
* @param array Array of `datasource_property`.name in uiOrder order
880
* @return int The matched sourceId.
882
public function getSourceId($property_array) {
885
$letters = array('a','b','c','d','e');
886
$from_clause = array();
887
$where_clause = array();
889
$sql = "SELECT a.sourceId AS 'sourceId' "
891
foreach ($property_array as $i=>$property) {
893
$property = mysqli_real_escape_string($this->_dbConnection->link,
896
$from_clause[] = 'datasource_property '.$letters[$i];
898
$where_clause[] = 'a.sourceId='.$letters[$i].'.sourceId';
900
$where_clause[] = $letters[$i].'.name="'.$property.'"';
901
$where_clause[] = $letters[$i].'.uiOrder='.++$i;
903
$sql .= implode(', ', $from_clause);
904
$sql .= ' WHERE ' . implode(' AND ', $where_clause);
907
$result = $this->_dbConnection->query($sql);
908
if ( $result->num_rows != 1 ) {
912
catch (Exception $e) {
916
$datasource = $result->fetch_array(MYSQLI_ASSOC);
917
return $datasource['sourceId'];
921
* Fetche the date of the oldest data from the `data` table for the
922
* specified data source identifier.
924
* @param int $sourceId Data source identifier
926
* @return date Date of the oldest row data
928
public function getOldestData($sourceId) {
934
. 'WHERE sourceId = %d '
935
. 'ORDER BY date ASC '
940
$result = $this->_dbConnection->query($sql);
942
catch (Exception $e) {
946
$data = $result->fetch_array(MYSQLI_ASSOC);
947
return $data['date'];
951
* Fetche the date of the newest data from the `data` table for the
952
* specified data source identifier.
954
* @param int $sourceId Data source identifier
956
* @return date Date of the newest row data
958
public function getNewestData($sourceId) {
964
. 'WHERE sourceId = %d '
965
. 'ORDER BY date DESC '
970
$result = $this->_dbConnection->query($sql);
972
catch (Exception $e) {
976
$data = $result->fetch_array(MYSQLI_ASSOC);
977
return $data['date'];
981
* Return a sorted array of Instruments with a sorted sub-array
982
* of datasource IDs and datasource names.
984
* @return array Sorted array of instruments with associated sources
986
public function getDataSourcesByInstrument() {
990
. 'dsp.name as "instName", '
992
. 'ds.name as "sourceName" '
996
. 'datasource_property dsp ON dsp.sourceId = ds.id '
998
. 'dsp.label = "Instrument" '
1000
. 'dsp.name, ds.name '
1001
. 'ORDER BY dsp.name';
1003
$result = $this->_dbConnection->query($sql);
1005
catch (Exception $e) {
1009
$return_array = array();
1010
while ( $row = $result->fetch_array(MYSQLI_ASSOC) ) {
1011
$return_array[$row['instName']][] = array(
1013
'name' => $row['sourceName'] );
1016
return $return_array;
1020
* Return a hierarchial list of the known data sources in one of
1023
* If $verbose is True, an alternative data structure is returned for
1024
* use with JHelioviewer. A hard-coded list of datasources is excluded
1025
* from the output by default, to prevent JHelioviewer crashes.
1027
* When $verbose is True, $enable may contain a string of top-level
1028
* data sources to re-enable. Example: '[STEREO_A,STEREO_B,PROBA2]'
1030
* @param bool $verbose true or false
1031
* @param string $enable array string of top-level sources to include
1033
* @return array A tree representation of the known data sources
1035
public function getDataSources($verbose=false, $enable=null) {
1036
$this->_dbConnect();
1038
// Support up to 5 levels of datasource hierarchy
1039
$letters = array('a','b','c','d','e');
1042
. 's.name ' .'AS nickname, '
1043
. 's.id ' .'AS id, '
1044
. 's.enabled ' .'AS enabled, '
1045
. 's.layeringOrder ' .'AS layeringOrder, '
1046
. 's.units ' .'AS units';
1048
foreach ($letters as $i=>$letter) {
1050
$sql .= $letter.'.name ' .'AS '.$letter.'_name, ';
1051
$sql .= $letter.'.description ' .'AS '.$letter.'_description, ';
1052
$sql .= $letter.'.label ' .'AS '.$letter.'_label';
1055
$sql .= ' FROM datasources s ';
1057
foreach ($letters as $i=>$letter) {
1058
$sql .= 'LEFT JOIN datasource_property '.$letter.' ';
1059
$sql .= 'ON s.id='.$letter.'.sourceId ';
1060
$sql .= 'AND '.$letter.'.uiOrder='.++$i.' ';
1063
// Verbose mode is for JHelioviewer
1064
// Older versions may crash if exposed to new "observatories"
1065
// By default, only include observatories in the array below
1066
// Also include any observatories specified in the $enable parameter
1068
$include_arr = array("SOHO","SDO");
1070
// Override hidden observatories if specified
1071
foreach($enable as $show) {
1072
if ( !in_array($show, $include_arr) ) {
1073
$include_arr[] = $show;
1077
// Prepare include list for "IN" clause
1079
foreach ($include_arr as $show) {
1080
$show = $this->_dbConnection->link->real_escape_string(
1082
$included .= "'$show',";
1084
$included = substr($included, 0, -1).")";
1086
if (sizeOf($include_arr) > 0) {
1087
$sql = substr($sql, 0, -1)." WHERE a.name IN $included";
1089
$sql = substr($sql, 0, -1)."";
1092
$sql .= ' ORDER BY a.name DESC;';
1096
// Use UTF-8 for responses
1097
$this->_dbConnection->setEncoding('utf8');
1099
// Fetch available data-sources
1100
$result = $this->_dbConnection->query($sql);
1102
while ($row = $result->fetch_array(MYSQLI_ASSOC)) {
1103
array_push($sources, $row);
1106
// Convert results into a more easily traversable tree structure
1108
foreach ($sources as $source) {
1110
// Only include if data is available for the specified source
1111
// as flagged in the `datasources` table
1112
if ( !(bool)$source["enabled"] ) {
1116
// Data Availability
1117
$newest = $this->getNewestData($source['id']);
1118
$oldest = $this->getOldestData($source['id']);
1120
// Determine depth of tree for this data source
1121
// And populate uiLabel array
1123
$uiLabels = array();
1124
foreach ($letters as $i=>$letter) {
1125
if ( $source[$letter.'_name'] !== null ) {
1126
$uiLabels[$i] = array(
1127
'label'=>$source[$letters[$i].'_label'],
1128
'name' =>$source[$letters[$i].'_name']);
1133
// Normal (non-verbose) format for Helioviewer.org
1137
foreach ($letters as $index=>$letter) {
1138
$key = $source[$letter.'_name'];
1139
if ( ++$index == $depth ) {
1140
$r[$key]['sourceId'] = (int)$source["id"];
1141
$r[$key]['nickname'] = $source["nickname"];
1142
$r[$key]['layeringOrder'] =
1143
(int)$source["layeringOrder"];
1144
$r[$key]['start'] = $oldest;
1145
$r[$key]['end'] = $newest;
1146
$r[$key]['uiLabels'] = $uiLabels;
1152
// Verbose format for JHelioviewer
1156
foreach ($letters as $index=>$letter) {
1157
$key = $source[$letter.'_name'];
1159
$desc = $source[$letter.'_description'];
1160
$label = $source[$letter.'_label'];
1162
$r[$key]['name'] = $name;
1163
$r[$key]['description'] = $desc;
1164
$r[$key]['label'] = $label;
1166
if ( ++$index == $depth ) {
1168
if (preg_match("/^\d*$/", $name)) {
1169
# \u205f = \xE2\x81\x9F = MEDIUM MATHEMATICAL SPACE
1170
$name = $name."\xE2\x81\x9F".$source['units'];
1173
$name = ucwords(str_replace("-", " ", $name));
1176
$r[$key]['name'] = $name;
1177
$r[$key]['description'] = $desc;
1178
$r[$key]['nickname'] = $source["nickname"];
1179
$r[$key]['sourceId'] = (int)$source["id"];
1180
$r[$key]['layeringOrder'] =
1181
(int)$source["layeringOrder"];
1182
$r[$key]['start'] = $oldest;
1183
$r[$key]['end'] = $newest;
1184
$r[$key]['label'] = $label;
1188
$r = &$r[$key]['children'];
1194
// Set defaults for verbose mode (JHelioviewer)
1196
$tree["SDO"]["default"]=true;
1197
$tree["SDO"]["children"]["AIA"]["default"]=true;
1198
$tree["SDO"]["children"]["AIA"]["children"]["171"]["default"]=true;
1205
* Return the full path to the date file from the specified source
1206
* most closely matching the given date.
1208
* @param string $date A UTC date string like "2003-10-05T00:00:00Z"
1209
* @param int $sourceId The data source identifier in the database
1211
* @return string Full path to the local data file
1214
public function getDataFilePath($date, $sourceId) {
1215
$img = $this->getDataFromDatabase($date, $sourceId);
1217
return $img['filepath'].'/'.$img['filename'];
1221
* Return the full path to the requested data file.
1223
* @param int $id Identifier in the `data` table
1225
* @return string Full path to the local data file
1227
public function getDataFilePathFromId($dataId) {
1228
$this->_dbConnect();
1231
'SELECT concat(filepath, "/", filename) AS filepath '
1238
$result = $this->_dbConnection->query($sql);
1240
catch (Exception $e) {
1244
$data = $result->fetch_array(MYSQLI_ASSOC);
1245
return $data['filepath'];
1249
* Return from the database the parameters that were used to generate
1252
* @param int Unique screenshot identifier
1254
* @return array Screenshot metadata
1256
public function getScreenshotMetadata($screenshotId) {
1257
$this->_dbConnect();
1259
$sql = sprintf('SELECT *, AsText(regionOfInterest) as roi ' .
1260
'FROM screenshots WHERE id=%d LIMIT 1;',
1264
$result = $this->_dbConnection->query($sql);
1266
catch (Exception $e) {
1270
return $result->fetch_array(MYSQLI_ASSOC);