Free cookie consent management tool by TermsFeed Policy Generator

Changeset 12467


Ignore:
Timestamp:
06/18/15 11:56:31 (9 years ago)
Author:
dglaser
Message:

#2388: Merged trunk into HiveStatistics branch

Location:
branches/HiveStatistics/sources
Files:
5 deleted
18 edited
6 copied

Legend:

Unmodified
Added
Removed
  • branches/HiveStatistics/sources

  • branches/HiveStatistics/sources/HeuristicLab.Analysis.Views

  • branches/HiveStatistics/sources/HeuristicLab.Analysis.Views/3.3/HistogramControl.Designer.cs

    r12143 r12467  
    4848    private void InitializeComponent() {
    4949      this.components = new System.ComponentModel.Container();
    50       System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
    51       System.Windows.Forms.DataVisualization.Charting.Legend legend1 = new System.Windows.Forms.DataVisualization.Charting.Legend();
    52       System.Windows.Forms.DataVisualization.Charting.Series series1 = new System.Windows.Forms.DataVisualization.Charting.Series();
     50      System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea2 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
     51      System.Windows.Forms.DataVisualization.Charting.Legend legend2 = new System.Windows.Forms.DataVisualization.Charting.Legend();
     52      System.Windows.Forms.DataVisualization.Charting.Series series2 = new System.Windows.Forms.DataVisualization.Charting.Series();
    5353      this.chart = new HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart();
    5454      this.binsNumericUpDown = new System.Windows.Forms.NumericUpDown();
     
    5757      this.label2 = new System.Windows.Forms.Label();
    5858      this.bandwidthNumericUpDown = new System.Windows.Forms.NumericUpDown();
     59      this.noDataLabel = new System.Windows.Forms.Label();
    5960      ((System.ComponentModel.ISupportInitialize)(this.chart)).BeginInit();
    6061      ((System.ComponentModel.ISupportInitialize)(this.binsNumericUpDown)).BeginInit();
     
    6768            | System.Windows.Forms.AnchorStyles.Left)
    6869            | System.Windows.Forms.AnchorStyles.Right)));
    69       chartArea1.Name = "ChartArea1";
    70       this.chart.ChartAreas.Add(chartArea1);
    71       legend1.Alignment = System.Drawing.StringAlignment.Center;
    72       legend1.Docking = System.Windows.Forms.DataVisualization.Charting.Docking.Top;
    73       legend1.Name = "Default";
    74       this.chart.Legends.Add(legend1);
     70      chartArea2.Name = "ChartArea1";
     71      this.chart.ChartAreas.Add(chartArea2);
     72      legend2.Alignment = System.Drawing.StringAlignment.Center;
     73      legend2.Docking = System.Windows.Forms.DataVisualization.Charting.Docking.Top;
     74      legend2.Name = "Default";
     75      this.chart.Legends.Add(legend2);
    7576      this.chart.Location = new System.Drawing.Point(0, 27);
    7677      this.chart.Name = "chart";
    77       series1.ChartArea = "ChartArea1";
    78       series1.Legend = "Default";
    79       series1.Name = "Series1";
    80       this.chart.Series.Add(series1);
     78      series2.ChartArea = "ChartArea1";
     79      series2.Legend = "Default";
     80      series2.Name = "Series1";
     81      this.chart.Series.Add(series2);
    8182      this.chart.Size = new System.Drawing.Size(465, 336);
    8283      this.chart.TabIndex = 0;
     
    159160      this.bandwidthNumericUpDown.ValueChanged += new System.EventHandler(this.bandwidthNumericUpDown_ValueChanged);
    160161      //
     162      // noDataLabel
     163      //
     164      this.noDataLabel.Anchor = System.Windows.Forms.AnchorStyles.None;
     165      this.noDataLabel.AutoSize = true;
     166      this.noDataLabel.Location = new System.Drawing.Point(163, 175);
     167      this.noDataLabel.Name = "noDataLabel";
     168      this.noDataLabel.Size = new System.Drawing.Size(139, 13);
     169      this.noDataLabel.TabIndex = 22;
     170      this.noDataLabel.Text = "No data could be displayed.";
     171      //
    161172      // HistogramControl
    162173      //
    163174      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
     175      this.Controls.Add(this.noDataLabel);
    164176      this.Controls.Add(this.label2);
    165177      this.Controls.Add(this.bandwidthNumericUpDown);
     
    186198    private System.Windows.Forms.Label label2;
    187199    private System.Windows.Forms.NumericUpDown bandwidthNumericUpDown;
     200    private System.Windows.Forms.Label noDataLabel;
    188201  }
    189202}
  • branches/HiveStatistics/sources/HeuristicLab.Analysis.Views/3.3/HistogramControl.cs

    r12173 r12467  
    139139        if (!point.Value.Any()) continue;
    140140
    141         Series histogramSeries = new Series(point.Key);
    142         chart.Series.Add(histogramSeries);
    143141        double minValue = point.Value.Min();
    144142        double maxValue = point.Value.Max();
    145143        double intervalWidth = (maxValue - minValue) / bins;
    146144        if (intervalWidth <= 0) continue;
     145
     146        Series histogramSeries = new Series(point.Key);
     147        chart.Series.Add(histogramSeries);
    147148
    148149        if (!exactCheckBox.Checked) {
     
    172173      }
    173174
     175      if (chart.Series.Any()) {
     176        noDataLabel.Visible = false;
     177      } else {
     178        noDataLabel.Visible = true;
     179      }
     180
    174181      ChartArea chartArea = chart.ChartAreas[0];
    175182      // don't show grid lines for second y-axis
  • branches/HiveStatistics/sources/HeuristicLab.ExtLibs

  • branches/HiveStatistics/sources/HeuristicLab.ExtLibs/HeuristicLab.EPPlus/4.0.3/EPPlus-4.0.3/ExcelWorkbook.cs

    r12074 r12467  
    337337        {
    338338          var font = Styles.Fonts[0];
     339#if __MonoCS__
     340    _standardFontWidth = (int)(font.Size * (2D / 3D)); //Aprox for Calibri.
     341#else
    339342                    try
    340343                    {
     
    374377                        _standardFontWidth = (int)(font.Size * (2D / 3D)); //Aprox for Calibri.
    375378                    }
     379#endif
    376380        }
    377381        return _standardFontWidth;
  • branches/HiveStatistics/sources/HeuristicLab.ExtLibs/HeuristicLab.EPPlus/4.0.3/HeuristicLab.EPPlus-4.0.3/HeuristicLab.EPPlus-4.0.3.csproj

    r12179 r12467  
    8989  <ItemGroup>
    9090    <None Include="epplus-4.0.3 memory improvement.diff" />
     91    <None Include="epplus-4.0.3-Mono.patch" />
    9192    <None Include="Plugin.cs.frame" />
    9293    <Compile Include="Plugin.cs" />
  • branches/HiveStatistics/sources/HeuristicLab.Persistence

  • branches/HiveStatistics/sources/HeuristicLab.Persistence/3.3/Default/Xml/XmlGenerator.cs

    r12012 r12467  
    311311    }
    312312
     313    private static void Serialize(object obj, Stream stream, Configuration config, bool includeAssemblies
     314   , CompressionLevel compression) {
     315      Serializer serializer = new Serializer(obj, config);
     316      Serialize(stream, includeAssemblies, compression, serializer);
     317    }
     318
     319    private static void Serialize(Stream stream, bool includeAssemblies, CompressionLevel compression, Serializer serializer) {
     320      try {
     321        DateTime start = DateTime.Now;
     322        serializer.InterleaveTypeInformation = false;
     323        XmlGenerator generator = new XmlGenerator();
     324        using (ZipArchive zipArchive = new ZipArchive(stream, ZipArchiveMode.Create)) {
     325          ZipArchiveEntry entry = zipArchive.CreateEntry("data.xml", compression);
     326          using (StreamWriter writer = new StreamWriter(entry.Open())) {
     327            foreach (ISerializationToken token in serializer) {
     328              string line = generator.Format(token);
     329              writer.Write(line);
     330            }
     331          }
     332          entry = zipArchive.CreateEntry("typecache.xml", compression);
     333          using (StreamWriter writer = new StreamWriter(entry.Open())) {
     334            foreach (string line in generator.Format(serializer.TypeCache)) {
     335              writer.Write(line);
     336            }
     337          }
     338          if (includeAssemblies) {
     339            foreach (string name in serializer.RequiredFiles) {
     340              Uri uri = new Uri(name);
     341              if (!uri.IsFile) {
     342                Logger.Warn("cannot read non-local files");
     343                continue;
     344              }
     345              entry = zipArchive.CreateEntry(Path.GetFileName(uri.PathAndQuery), compression);
     346              using (BinaryWriter bw = new BinaryWriter(entry.Open())) {
     347                using (FileStream reader = File.OpenRead(uri.PathAndQuery)) {
     348                  byte[] buffer = new byte[1024 * 1024];
     349                  while (true) {
     350                    int bytesRead = reader.Read(buffer, 0, 1024 * 1024);
     351                    if (bytesRead == 0)
     352                      break;
     353                    bw.Write(buffer, 0, bytesRead);
     354                  }
     355                }
     356              }
     357            }
     358          }
     359        }
     360        Logger.Info(String.Format("serialization took {0} seconds with compression level {1}",
     361          (DateTime.Now - start).TotalSeconds, compression));
     362      }
     363      catch (Exception) {
     364        Logger.Warn("Exception caught, no data has been serialized.");
     365        throw;
     366      }
     367    }
     368
    313369    /// <summary>
    314370    /// Serializes the specified object into a file.
     
    322378      try {
    323379        string tempfile = Path.GetTempFileName();
    324         DateTime start = DateTime.Now;
     380
    325381        using (FileStream stream = File.Create(tempfile)) {
    326           Serializer serializer = new Serializer(obj, config);
    327           serializer.InterleaveTypeInformation = false;
    328           XmlGenerator generator = new XmlGenerator();
    329           using (ZipArchive zipArchive = new ZipArchive(stream, ZipArchiveMode.Create)) {
    330             ZipArchiveEntry entry = zipArchive.CreateEntry("data.xml", compression);
    331             using (StreamWriter writer = new StreamWriter(entry.Open())) {
    332               foreach (ISerializationToken token in serializer) {
    333                 string line = generator.Format(token);
    334                 writer.Write(line);
    335               }
    336             }
    337             entry = zipArchive.CreateEntry("typecache.xml", compression);
    338             using (StreamWriter writer = new StreamWriter(entry.Open())) {
    339               foreach (string line in generator.Format(serializer.TypeCache)) {
    340                 writer.Write(line);
    341               }
    342             }
    343             if (includeAssemblies) {
    344               foreach (string name in serializer.RequiredFiles) {
    345                 Uri uri = new Uri(name);
    346                 if (!uri.IsFile) {
    347                   Logger.Warn("cannot read non-local files");
    348                   continue;
    349                 }
    350                 entry = zipArchive.CreateEntry(Path.GetFileName(uri.PathAndQuery), compression);
    351                 using (BinaryWriter bw = new BinaryWriter(entry.Open())) {
    352                   using (FileStream reader = File.OpenRead(uri.PathAndQuery)) {
    353                     byte[] buffer = new byte[1024 * 1024];
    354                     while (true) {
    355                       int bytesRead = reader.Read(buffer, 0, 1024 * 1024);
    356                       if (bytesRead == 0)
    357                         break;
    358                       bw.Write(buffer, 0, bytesRead);
    359                     }
    360                   }
    361                 }
    362               }
    363             }
    364           }
    365         }
    366         Logger.Info(String.Format("serialization took {0} seconds with compression level {1}",
    367           (DateTime.Now - start).TotalSeconds, compression));
     382          Serialize(obj, stream, config, includeAssemblies, compression);
     383        }
     384
    368385        File.Copy(tempfile, filename, true);
    369386        File.Delete(tempfile);
     
    381398    /// <param name="obj">The object.</param>
    382399    /// <param name="stream">The stream.</param>
    383     public static void Serialize(object obj, Stream stream) {
    384       Serialize(obj, stream, ConfigurationService.Instance.GetConfiguration(new XmlFormat()));
     400    /// <param name="useZip">If true, uses zip for compression, otherwise gzip.</param>
     401    public static void Serialize(object obj, Stream stream, bool useZip = false) {
     402      Serialize(obj, stream, ConfigurationService.Instance.GetConfiguration(new XmlFormat()), useZip);
    385403    }
    386404
     
    392410    /// <param name="stream">The stream.</param>
    393411    /// <param name="config">The configuration.</param>
    394     public static void Serialize(object obj, Stream stream, Configuration config) {
    395       Serialize(obj, stream, config, false);
     412    /// <param name="useZip">If true, uses zip for compression, otherwise gzip.</param>
     413    public static void Serialize(object obj, Stream stream, Configuration config, bool useZip = false) {
     414      Serialize(obj, stream, config, false, useZip);
    396415    }
    397416
     
    403422    /// <param name="config">The configuration.</param>
    404423    /// <param name="includeAssemblies">if set to <c>true</c> include need assemblies.</param>
    405     public static void Serialize(object obj, Stream stream, Configuration config, bool includeAssemblies) {
     424    /// <param name="useZip">If true, uses zip for compression, otherwise gzip.</param>
     425    public static void Serialize(object obj, Stream stream, Configuration config, bool includeAssemblies, bool useZip = false) {
    406426      try {
    407427        Serializer serializer = new Serializer(obj, config);
    408         Serialize(stream, serializer);
     428        if (useZip) {
     429          Serialize(obj, stream, config, includeAssemblies, CompressionLevel.Optimal);
     430        } else {
     431          Serialize(stream, serializer);
     432        }
    409433      }
    410434      catch (PersistenceException) {
     
    424448    /// <param name="includeAssemblies">if set to <c>true</c> include need assemblies.</param>
    425449    /// <param name="types">The list of all serialized types.</param>
    426     public static void Serialize(object obj, Stream stream, Configuration config, bool includeAssemblies, out IEnumerable<Type> types) {
     450    /// <param name="useZip">If true, uses zip for compression, otherwise gzip.</param>
     451    public static void Serialize(object obj, Stream stream, Configuration config, bool includeAssemblies, out IEnumerable<Type> types, bool useZip = false) {
    427452      try {
    428453        Serializer serializer = new Serializer(obj, config);
    429         Serialize(stream, serializer);
     454        if (useZip) {
     455          Serialize(stream, includeAssemblies, CompressionLevel.Optimal, serializer);
     456        } else {
     457          Serialize(stream, serializer);
     458        }
    430459        types = serializer.SerializedTypes;
    431460      }
  • branches/HiveStatistics/sources/HeuristicLab.Persistence/3.3/Default/Xml/XmlParser.cs

    r12012 r12467  
    218218
    219219    /// <summary>
    220     /// Deserializes an object from the specified stream.
     220    /// Deserializes an object from the specified stream using GZip compression.
    221221    /// </summary>
    222222    /// <param name="stream">The stream.</param>
    223223    /// <returns>A fresh object instance.</returns>
    224     public static object Deserialize(Stream stream) {
     224    private static object DeserializeWithGZip(Stream stream) {
    225225      try {
    226226        using (StreamReader reader = new StreamReader(new GZipStream(stream, CompressionMode.Decompress))) {
     
    239239
    240240    /// <summary>
     241    /// Deserializes an object from the specified stream using Zip compression.
     242    /// </summary>
     243    /// <param name="stream">The stream.</param>
     244    /// <returns>A fresh object instance.</returns>
     245    private static object DeserializeWithZip(Stream stream) {
     246      ZipArchive zipFile = new ZipArchive(stream);
     247      return Deserialize(zipFile);
     248    }
     249
     250    /// <summary>
    241251    /// Deserializes an object from the specified stream.
    242252    /// </summary>
    243253    /// <typeparam name="T">object type expected from the serialized stream</typeparam>
    244254    /// <param name="stream">The stream.</param>
     255    /// <param name="useZip">If true, uses zip for decompression, otherwise gzip.</param>
    245256    /// <returns>A fresh object instance.</returns>
    246     public static T Deserialize<T>(Stream stream) {
    247       return (T)Deserialize(stream);
     257    public static T Deserialize<T>(Stream stream, bool useZip = false) {
     258      return (T)Deserialize(stream, useZip);
     259    }
     260
     261    /// <summary>
     262    /// Deserializes an object from the specified stream.
     263    /// </summary>
     264    /// <param name="stream">The stream.</param>
     265    /// <param name="useZip">If true, uses zip for decompression, otherwise gzip.</param>
     266    /// <returns>A fresh object instance.</returns>
     267    public static object Deserialize(Stream stream, bool useZip = false) {
     268      if (useZip) {
     269        return DeserializeWithZip(stream);
     270      } else {
     271        return DeserializeWithGZip(stream);
     272      }
    248273    }
    249274
  • branches/HiveStatistics/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification

  • branches/HiveStatistics/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationPruningOperator.cs

    r12358 r12467  
    8585      var model = modelCreator.CreateSymbolicClassificationModel(clonedTree, interpreter, estimationLimits.Lower, estimationLimits.Upper);
    8686
    87       var nodes = clonedTree.IterateNodesPrefix().ToList();
     87      var nodes = clonedTree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPrefix().ToList();
    8888      double quality = Evaluate(model, problemData, rows);
    8989
  • branches/HiveStatistics/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression

  • branches/HiveStatistics/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionPruningOperator.cs

    r12358 r12467  
    7171      var clonedTree = (ISymbolicExpressionTree)tree.Clone();
    7272      var model = new SymbolicRegressionModel(clonedTree, interpreter, estimationLimits.Lower, estimationLimits.Upper);
    73       var nodes = clonedTree.IterateNodesPrefix().ToList();
     73      var nodes = clonedTree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPrefix().ToList(); // skip the nodes corresponding to the ProgramRootSymbol and the StartSymbol
    7474      double quality = Evaluate(model, problemData, rows);
    7575
  • branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Status/3.3/WebApi/DataController.cs

    r12435 r12467  
    2222using System;
    2323using System.Collections.Generic;
     24using System.Data.Linq;
    2425using System.Linq;
    2526using System.Web.Http;
     
    4243        SELECT
    4344          DISTINCT UserId,
    44           (SELECT Count FROM UserTasks WHERE TaskState = 'Calculating' AND UserId = ut.UserId) AS CalculatingTasks,
    45           (SELECT Count FROM UserTasks WHERE TaskState = 'Waiting' AND UserId = ut.UserId) AS WaitingTasks
     45          ISNULL((SELECT Count FROM UserTasks WHERE TaskState = 'Calculating' AND UserId = ut.UserId), 0) AS CalculatingTasks,
     46          ISNULL((SELECT Count FROM UserTasks WHERE TaskState = 'Waiting' AND UserId = ut.UserId), 0) AS WaitingTasks
    4647        FROM UserTasks ut;";
    47 
    4848
    4949    private class UserTaskStatus {
     
    7373        var activeSlaves = onlineSlaves.Where(s => s.IsAllowedToCalculate).ToList();
    7474        var calculatingSlaves = activeSlaves.Where(s => s.SlaveState == SlaveState.Calculating).ToList();
    75 
    7675        int calculatingMemory = calculatingSlaves.Any() ? (int)calculatingSlaves.Sum(s => s.Memory) / 1024 : 0;
    7776        int freeCalculatingMemory = calculatingSlaves.Any() ? (int)calculatingSlaves.Sum(s => s.FreeMemory) / 1024 : 0;
     
    129128      }
    130129      using (var db = new HiveDataContext()) {
    131         var statistics = db.Statistics.Where(s => s.Timestamp >= start && s.Timestamp <= end);
     130        DataLoadOptions loadOptions = new DataLoadOptions();
     131        loadOptions.LoadWith<Statistics>(o => o.SlaveStatistics);
     132        db.LoadOptions = loadOptions;
     133        db.DeferredLoadingEnabled = false;
     134        var statistics = db.Statistics.Where(s => s.Timestamp >= start && s.Timestamp <= end)
     135                                      .OrderBy(s => s.Timestamp)
     136                                      .ToList();
    132137        var status = new DTO.Status {
    133138          CoreStatus = new DTO.CoreStatus(),
  • branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Status/3.3/WebApp/status/statusCtrl.js

    r12435 r12467  
    143143                    // charts are currently filled with old total/used data
    144144                    // start temporary
    145                     var usedCores = status.CoreStatus.TotalCores - status.getCoreStatus.FreeCores;
     145                    var usedCores = status.CoreStatus.TotalCores - status.CoreStatus.FreeCores;
    146146                    var usedMemory = status.MemoryStatus.TotalMemory - status.MemoryStatus.FreeMemory;
    147147                    // end temporary
  • branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/HeuristicLab.Services.WebApp-3.3.csproj

    r12428 r12467  
    214214    <Content Include="HeuristicLab.snk" />
    215215    <Content Include="Properties\AssemblyInfo.cs.frame" />
    216     <Content Include="Web.config" />
     216    <Content Include="Web.config">
     217      <SubType>Designer</SubType>
     218    </Content>
    217219    <Content Include="Web.Debug.config">
    218220      <DependentUpon>Web.config</DependentUpon>
  • branches/HiveStatistics/sources/prepareProjectsForMono.sh

    r9702 r12467  
    1313unamestr=`uname`
    1414if [[ "$unamestr" == 'Darwin' ]]; then
    15    
    16    awk '/ProtocolBuffers-2.4.1.473|ProtoGen-2.4.1.473|HeuristicLab.ProtobufCS-2.4.1.473/ {while (/ProtocolBuffers-2.4.1.473|ProtoGen-2.4.1.473|HeuristicLab.ProtobufCS-2.4.1.473/ && getline>0) ; next} 1' HeuristicLab.ExtLibs.sln > tmp
     15   awk '/ICSharpCode.AvalonEdit-5.0.1|HeuristicLab.AvalonEdit-5.0.1/ {while (/ICSharpCode.AvalonEdit-5.0.1|HeuristicLab.AvalonEdit-5.0.1/ && getline>0) ; next} 1' HeuristicLab.ExtLibs.sln > tmp
    1716   mv tmp HeuristicLab.ExtLibs.sln
    18 
    19    awk '/HeuristicLab.Problems.ExternalEvaluation-3.3|HeuristicLab.Problems.ExternalEvaluation.GP-3.4|HeuristicLab.Problems.ExternalEvaluation.Views-3.3/ {while (/HeuristicLab.Problems.ExternalEvaluation-3.3|HeuristicLab.Problems.ExternalEvaluation.GP-3.4|HeuristicLab.Problems.ExternalEvaluation.Views-3.3/ && getline>0) ; next} 1' "HeuristicLab 3.3.sln" > tmp
    20    mv tmp "HeuristicLab 3.3.sln"
    21 
    2217elif [[ "$unamestr" == 'Linux' ]]; then
    23    sed -e '/ProtocolBuffers-2.4.1.473/,+1d' -e '/ProtoGen-2.4.1.473/,+1d' -e '/HeuristicLab.ProtobufCS-2.4.1.473/,+1d' HeuristicLab.ExtLibs.sln > tmp
     18   sed -e '/ICSharpCode.AvalonEdit-5.0.1/,+1d' -e '/HeuristicLab.AvalonEdit-5.0.1/,+1d' HeuristicLab.ExtLibs.sln > tmp
    2419   mv tmp HeuristicLab.ExtLibs.sln
    25 
    26    sed -e '/HeuristicLab.Problems.ExternalEvaluation-3.3/,+1d' -e '/HeuristicLab.Problems.ExternalEvaluation.GP-3.4/,+1d' -e '/HeuristicLab.Problems.ExternalEvaluation.Views-3.3/,+1d' "HeuristicLab 3.3.sln" > tmp
    27    mv tmp "HeuristicLab 3.3.sln"
    2820else
    2921   echo "Unsupported operating system, compiling HeuristicLab may not work!"
Note: See TracChangeset for help on using the changeset viewer.