try this.
You have to put skin.conf in your images directory. 
In imagegenerator you can find the code as "by Andrea" related to previous 
year and previous month of the year before. If you are able to modified the 
code you can get what you want.

Here is the webpage with the previous year graph.
http://meteonibbio.altervista.org/station/Bootstrap/index.html

bye
Andrea



Il giorno mercoledì 6 maggio 2020 19:49:44 UTC+2, Tomáš Filo ha scritto:
>
> And i would by nice to have this feature as part of ImageGenerator. 
> Configurable from skin. For now when I want to generate images for 
> historical records I use "wee_reports weewx.conf timestamp" and custom 
> weewx.conf and skin to generate just  hostorical plots. It works but it is 
> workaround.
>
> Dňa streda, 6. mája 2020 18:14:55 UTC+2 Tomáš Filo napísal(a):
>>
>> Thank's for replay, where cat I find this implementation ?
>>
>> Dňa streda, 6. mája 2020 17:36:03 UTC+2 Andrea napísal(a):
>>>
>>> I have implemented report for an year before or the month of the year 
>>> before. Probably it can be simple adjust to have what you ask.
>>>
>>> Il giorno mercoledì 6 maggio 2020 17:17:18 UTC+2, Tomáš Filo ha scritto:
>>>>
>>>> Hello, Is it possible to force ImageGenerator to generate images not 
>>>> for only last day, week, month, year but for every month and year. I use 
>>>> instead of text NOAA html templates. And I would like to display plosts 
>>>> for 
>>>> every month and year possible. 
>>>>
>>>> Now I have daytempdew.png, monthtempdew.png but I want to generate 
>>>> 2019-01-tempdew.png, 2019-02-tempdew.png etc.
>>>>
>>>> Thank you.
>>>>
>>>>
>>>>

-- 
You received this message because you are subscribed to the Google Groups 
"weewx-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to weewx-user+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/weewx-user/d86e42ba-466c-49c2-930f-9d5a43c38acc%40googlegroups.com.
############################################################################################
############################################################################################
#                                                                               
           #
#                                                                               
           #
#                          STANDARD SKIN CONFIGURATION FILE                     
           #
#                                                                               
           #
#                                                                               
           #
############################################################################################
#                                                                               
           #
#                    Copyright (c) 2010 Tom Keffer <tkef...@gmail.com>          
           #
#                                                                               
           #
#                      See the file LICENSE.txt for your full rights.           
           #
#                                                                               
           #
############################################################################################
#
#    $Revision: 737 $
#    $Author: tkeffer $
#    $Date: 2012-11-04 09:05:51 -0800 (Sun, 04 Nov 2012) $
#
############################################################################################

[Extras]

    #
    # Put any extra tags here that you want to be available in the templates
    #
    
############################################################################################

[Units]

    #
    # This section is for managing the selection and formatting of units.
    #
    
    [[Groups]]
        #
        # For each group of measurements, this section sets what units to use 
for it.
        # NB: The unit is always in the singular. I.e., 'mile_per_hour', NOT 
'miles_per_hour'
        # 
        group_altitude     = meter                # Options are 'foot' or 
'meter'
        group_degree_day   = degree_C_day         # Options are 'degree_F_day' 
or 'degree_C_day'
        group_direction    = degree_compass
        group_moisture     = centibar
        group_percent      = percent
        group_pressure     = mbar                 # Options are 'inHg', 'mmHg', 
'mbar', or 'hPa'
        group_radiation    = watt_per_meter_squared
        group_rain         = mm                   # Options are 'inch', 'cm', 
or 'mm'
        group_rainrate     = mm_per_hour          # Options are 
'inch_per_hour', 'cm_per_hour', or 'mm_per_hour'
        group_speed        = knot                 # Options are 
'mile_per_hour', 'km_per_hour', 'knot', or 'meter_per_second'
        group_speed2       = knot2                # Options are 
'mile_per_hour2', 'km_per_hour2', 'knot2', or 'meter_per_second2'
        group_temperature  = degree_C             # Options are 'degree_F' or 
'degree_C'
        group_uv           = uv_index
        group_volt         = volt

        # The following unit groups are used internally and should not be 
changed:
        group_count        = count
        group_interval     = minute
        group_time         = unix_epoch

    [[StringFormats]]
        #
        # This section sets the string formatting for each type of unit.
        #
        centibar           = %.0f
        cm                 = %.2f
        cm_per_hour        = %.2f
        degree_C           = %.1f
        degree_F           = %.1f
        degree_compass     = %.0f
        foot               = %.0f
        hPa                = %.1f
        inHg               = %.3f
        inch               = %.2f
        inch_per_hour      = %.2f
        km_per_hour        = %.0f
        km_per_hour2       = %.1f
        knot               = %.0f
        knot2              = %.1f
        mbar               = %.1f
        meter              = %.0f
        meter_per_second   = %.1f
        meter_per_second2  = %.1f
        mile_per_hour      = %.0f
        mile_per_hour2     = %.1f
        mm                 = %.1f
        mmHg               = %.1f
        mm_per_hour        = %.1f
        percent            = %.0f
        uv_index           = %.1f
        volt               = %.1f
        watt_per_meter_squared = %.0f
        NONE               = "    --"

    [[Labels]]
        #
        # This section sets a label to be used for each type of unit.
        #
        centibar          = " cb"
        cm                = " cm"
        cm_per_hour       = " cm/hr"
        degree_C          = " °C"
        degree_F          = " °F"
        degree_compass    = " °"
        foot              = " feet"
        hPa               = " hPa"
        inHg              = " inHg"
        inch              = " in"
        inch_per_hour     = " in/hr"
        km_per_hour       = " kph"
        km_per_hour2      = " kph"
        knot              = " knots"
        knot2             = " knots"
        mbar              = " mbar"
        meter             = " meters"
        meter_per_second  = " m/s"
        meter_per_second2 = " m/s"
        mile_per_hour     = " mph"
        mile_per_hour2    = " mph"
        mm                = " mm"
        mmHg              = " mmHg"
        mm_per_hour       = " mm/hr"
        percent           =   %
        volt              = " V"
        watt_per_meter_squared = " W/m²"
        NONE              = ""
        
    [[TimeFormats]]
        #
        # This section sets the string format to be used
        # each time scale.
        #
        day        = %H:%M
        week       = %H:%M on %A
        month      = %d-%b-%Y %H:%M
        year       = %d-%b-%Y %H:%M
        rainyear   = %d-%b-%Y %H:%M
        current    = %d-%b-%Y %H:%M
        ephem_day  = %H:%M
        ephem_year = %d-%b-%Y %H:%M

        [[DegreeDays]]
          #
          # This section sets the base temperatures used for the calculation
          # of heating and cooling degree-days.
          #
                
          # Base temperature for heating days, with unit:
          heating_base = 15, degree_C
          # Base temperature for cooling days, with unit:
          cooling_base = 15, degree_C

    [[Trend]]
        time_delta = 7200  # 2 hours  --10800
        time_grace = 60    # 1 minutes --120

############################################################################################

[Labels]
    
    #
    # Generic labels
    #
    
    # Set to hemisphere abbreviations suitable for your location: 
    hemispheres = N, S, E, W

    [[Generic]]
        #
        # Generic labels, keyed by an observation type.
        #
        barometer      = Barometer
        dewpoint       = Dew Point
        heatindex      = Heat Index
        inHumidity     = In Humidity
        inTemp         = In Temp
        outHumidity    = Out Humidity
        outTemp        = Out Temp
        radiation      = Radiation
        rain           = Rain
        rainRate       = Rain Rate
        rxCheckPercent = ISS Signal Quality
        windDir        = Wind Direction
        windGust       = Gust Speed
        windGustDir    = Gust Direction
        windSpeed      = Wind Speed
        windchill      = Wind Chill
        windgustvec    = Gust Vector
        windvec        = Wind Vector
    
        # This one is probably specific to my station!
 #       extraTemp1     = Pond Temperature

###############################################################

[Language]

    #
    # Set a language below and labels will be overridden with any that are 
specified in
    # skins/languages/[language].conf
    #
    # Choices are: espanol

    # language = italian


[ImageGenerator]
    
    # 
    # This section lists all the images to be generated, what SQL types are to
    # be included in them, along with many plotting options, such as color or
    # font. There's a default for almost everything, if not specified
    # below. Nevertheless, I've explicitly put in values, to make it easy to see
    # and understand the options.
    #
    # Fonts can be anything accepted by the Python Imaging Library (PIL), which
    # is currently truetype (.ttf), or PIL's own font format (.pil). See
    # http://www.pythonware.com/library/pil/handbook/imagefont.htm for more
    # details.  Note that "font size" is only used with truetype (.ttf)
    # fonts. For others, font size is determined by the bit-mapped size, usually
    # encoded in the file name (e.g., courB010.pil). If a font can't be found,
    # then a default font will be used.
    #
    # Anti-aliasing
    #
    anti_alias = 3
    show_daynight = true

    # These control the appearance of the bands if they are shown.
    # Here's a monochrome scheme:
    # daynight_day_color   = 0xdfdfdf
    # daynight_night_color = 0xffff00
    # daynight_edge_color  = 0xd0d0d0

    # Here's an alternative, using a blue/yellow tint:
    # daynight_day_color   = 0xf8ffff
    # daynight_night_color = 0xfff8f8
    # daynight_edge_color  = 0xf8f8ff
    
    # Richie's day-night colors
    # daynight_day_color   = 0xf8ffff
    # daynight_night_color = 0xbcffde
    # daynight_edge_color  = 0xd9ffd1

    # Nick's values - frankly monocrhome is best
    daynight_day_color   = 0xdfdfdf
    daynight_night_color = 0xbbbbbb
    daynight_edge_color  = 0xd0d0d0     

    image_width = 920  #550
    image_height = 275  #350
    image_background_color = 0xffffff
    
    chart_background_color = 0xffffff
    chart_gridline_color = 0xa0a0a0
    
    top_label_font_path = /usr/share/fonts/truetype/freefont/FreeMonoBold.ttf
    top_label_font_size = 18
    
    unit_label_font_path = /usr/share/fonts/truetype/freefont/FreeMonoBold.ttf
    unit_label_font_size = 14
    unit_label_font_color = 0x000000
    
    bottom_label_font_path = /usr/share/fonts/truetype/freefont/FreeMonoBold.ttf
    bottom_label_font_size = 14
    bottom_label_font_color = 0x000000
    
    axis_label_font_path = /usr/share/fonts/truetype/freefont/FreeMonoBold.ttf
    axis_label_font_size = 14
    axis_label_font_color = 0x000000
    
    # Options for the compass rose, used for progressive vector plots
    rose_label = N
    rose_label_font_path = /usr/share/fonts/truetype/freefont/FreeMonoBold.ttf
    rose_label_font_size  = 12
    rose_label_font_color = 0x000000

    # Default colors for the plot lines. These can be overridden for
    # individual lines using option 'color'
    chart_line_colors = 0xb48242, 0x4242b4, 0x42b442
    
        # Type of line. Only 'solid' or 'none' is offered now    
    line_type = 'solid'

    # Size of marker in pixels
    marker_size = 8
        # Type of marker. Pick one of 'cross', 'x', 'circle', 'box', or 'none'
    marker_type ='none'
    
    ##
    ## What follows is a list of subsections, each specifying a time span, such
    ## as a day, week, month, or year. There's nothing special about them or
    ## their names: it's just a convenient way to group plots with a time span
    ## in common. You could add a time span [[biweek_images]] and add the
    ## appropriate time length, aggregation strategy, etc., without changing any
    ## code.
    ##
    ## Within each time span, each sub-subsection is the name of a plot to be
    ## generated for that time span. The generated plot will be stored using
    ## that name, in whatever directory was specified by option 'HTML_ROOT'
    ## in weewx.conf.
    ##
    ## With one final nesting (four brackets!) is the sql type of each line to
    ## be included within that plot.
    ##
    ## Unless overridden, leaf nodes inherit options from their parent
    ##
    
    # Default plot and aggregation. Can get overridden at any level.
    
    plot_type = line
    aggregate_type = none
    width = 1
    time_length = 86400    # == 24 hours
#    line_gap_fraction = 0.01

#################
### DAY Images

    [[day_images]]
        x_label_format = %H
#        x_label_format = %H:%M
        width = 2
#        bottom_label_format = %x %X
        
        bottom_label_format = %d/%m/%y %X
        time_length = 97200    # == 27 hours
 #       time_length = 129600    # == 36 hours
        
        [[[daybarometer-Bootstrap]]]
            [[[[barometer]]]]
                x_label_format = %d/%m
                time_length = 172800    # == 48 hours
                    aggregate_type = avg
                aggregate_interval = 21600  #  6 hours
        
        [[[daytempdew-Bootstrap]]]
            [[[[outTemp]]]]
            [[[[extraTemp2]]]]
                label = HeatDegDays
            [[[[extraTemp3]]]]
                label = CoolDegDays

        [[[dayrain-Bootstrap]]]
            # Make sure the y-axis increment is at least 0.02 for the rain plot
            yscale = None, None, 0.02
            plot_type = bar
            [[[[rain]]]]
                aggregate_type = sum
                aggregate_interval = 900   # 15 min 
 #               label = Rain (hourly total)
                    
        [[[dayinside-Bootstrap]]]
            [[[[inTemp]]]]

        [[[dayhumid-Bootstrap]]]
        #    x_label_format = %d
           aggregate_interval = 600    # == 10 min
           [[[[outHumidity]]]]
           [[[[inHumidity]]]]

        [[[daywind-Bootstrap]]]
            [[[[windSpeed]]]]
            [[[[windGust]]]]              
        
        [[[daywinddir-Bootstrap]]]
            # Hardwire in the y-axis scale for wind direction:
            yscale = 0.0, 360.0, 45.0
            # Don't join lines
            # Type of line. Only 'solid' or 'none' is offered now   
                   line_type = 'none'
            # Size of marker in pixels
            marker_size = 6
                 # Type of marker. Pick one of 'cross', 'x', 'circle', 'box', 
or 'none'
            marker_type ='cross'
            [[[[windDir]]]]
        
#############
### WEEK Images
          
    [[week_images]]
        x_label_format = %d
#        bottom_label_format = %x %X
        bottom_label_format = %d/%m/%y %X
        time_length = 604800    # == 7 days
        aggregate_type = avg
        aggregate_interval = 7200   # 2 hh
        width = 2
        
        [[[weekbarometer-Bootstrap]]]
            [[[[barometer]]]]
        
        [[[weektempdew-Bootstrap]]]
            [[[[outTemp]]]]   
            [[[[extraTemp2]]]]
                label = HeatDegDays
            [[[[extraTemp3]]]]
                label = CoolDegDays
        
        [[[weekrain-Bootstrap]]]
            yscale = None, None, 0.02
            plot_type = bar
            [[[[rain]]]]
                aggregate_type = sum
                aggregate_interval = 86400
                label = Rain (daily total)
               
        [[[weekinside-Bootstrap]]]
            [[[[inTemp]]]]

        [[[weekwind-Bootstrap]]]
            [[[[windSpeed]]]]
            [[[[windGust]]]]              
        
        [[[weekwinddir-Bootstrap]]]
            # Hardwire in the y-axis scale for wind direction:
            yscale = 0.0, 360.0, 45.0
            # Don't join lines
            # Type of line. Only 'solid' or 'none' is offered now   
                 line_type = 'none'
            # Size of marker in pixels
            marker_size = 6
                 # Type of marker. Pick one of 'cross', 'x', 'circle', 'box', 
or 'none'
            marker_type ='cross'
            [[[[windDir]]]]


#############
### MONTH Images

    [[month_images]]
        x_label_format = %d
#        bottom_label_format = %x %X
        bottom_label_format = %d/%m/%y %X
        time_length = 2678400    # == 31 days
        aggregate_type = avg
        aggregate_interval = 86400    # == 1 giorno
        show_daynight = false
               width = 2
        
        [[[monthbarometer-Bootstrap]]]
            [[[[barometer]]]]
        
        [[[monthtempdew-Bootstrap]]]
            yscale = 0.0, 35.0, 5.0
            label = Monthly Out Temp
              [[[[outTemp]]]]
              [[[[extraTemp2]]]]
                label = HeatDegDays
              [[[[extraTemp3]]]]
                label = CoolDegDays
        
        [[[monthrain-Bootstrap]]]
            yscale = None, None, 0.02
            plot_type = bar
            [[[[rain]]]]
                aggregate_type = sum
                aggregate_interval = 86400
                label = Rain (daily total)
                   
        [[[monthinside-Bootstrap]]]
            yscale = 0.0, 35.0, 5.0
            [[[[inTemp]]]]

        [[[monthwind-Bootstrap]]]
            [[[[windSpeed]]]]
            [[[[windGust]]]]              
        
        [[[monthwinddir-Bootstrap]]]
            # Hardwire in the y-axis scale for wind direction:
            yscale = 0.0, 360.0, 45.0
            # Don't join lines
            # Type of line. Only 'solid' or 'none' is offered now   
                 line_type = 'none'
            # Size of marker in pixels
            marker_size = 6
                 # Type of marker. Pick one of 'cross', 'x', 'circle', 'box', 
or 'none'
            marker_type = 'cross'
            [[[[windDir]]]]        

#############
### YEAR Images
       
    [[year_images]]
        x_label_format = %b/%y             ####x_label_format = %d/%m
#        bottom_label_format = %x %X
        bottom_label_format = %d/%m/%y %X
        time_length = 34128000    # == 365 days +30gg
        aggregate_type = avg
        aggregate_interval = 432000   #  -- 5 gg 
        show_daynight = false
        width = 2
        
        [[[yearbarometer-Bootstrap]]]
#           aggregate_interval = 604800   # 1 week
            [[[[barometer]]]]
        
        [[[yeartempdew-Bootstrap]]]
            yscale = 0.0, 35.0, 5.0
            label = Yearly Out Temp
            [[[[outTemp]]]]
            
        [[[yearinside-Bootstrap]]]
            [[[[inTemp]]]]
        
        # Daily high/lows:
        [[[yearhilow-Bootstrap]]]
            [[[[hi]]]]
                data_type = outTemp
                aggregate_type = max
                label = High
            [[[[low]]]]
                data_type = outTemp
                aggregate_type = min
                label = Low Temp
                
       [[[yearrain-Bootstrap]]]
            yscale = None, None, 0.02
            plot_type = bar
            [[[[rain]]]]
                aggregate_type = sum
                aggregate_interval = 2629800 # Magic number: the length of a 
nominal month
                label = Rain (weekly total)

        [[[yearwind-Bootstrap]]]
            [[[[windSpeed]]]]
            [[[[windGust]]]]              
        
        [[[yearwinddir-Bootstrap]]]
            # Hardwire in the y-axis scale for wind direction:
            yscale = 0.0, 360.0, 45.0
            # Don't join lines
            # Type of line. Only 'solid' or 'none' is offered now   
                 line_type = 'none'
            # Size of marker in pixels
            marker_size = 6
                 # Type of marker. Pick one of 'cross', 'x', 'circle', 'box', 
or 'none'
            marker_type = 'cross'
            [[[[windDir]]]] 
                aggregate_type = avg
 #               aggregate_interval = 1209600   # 2 sett

#############################
### Last Year / Month Images

        [[[lastyeartempdew-Bootstrap]]]
            x_label_format = %b/%y             ####x_label_format = %d/%m
#            bottom_label_format = %x %X
            bottom_label_format = %d/%m/%y %X
            time_length = 31622400    # == 366 days
            aggregate_type = avg
            aggregate_interval = 432000   # 5 gg 
            show_daynight = false
            width = 2
            yscale = 0.0, 35.0, 5.0
            label = Out Temp Year Before
            color = 0x42b442
            previous_year = -1
            report_timing = @yearly
                [[[[outTemp]]]]

        [[[lastmonthtempdew-Bootstrap]]]
            x_label_format = %d/%m     ###### %d/%b
            bottom_label_format = %x %X
            time_length = 2678400    # == 31 days
            aggregate_type = avg
            aggregate_interval = 86400    # == 1 giorno
            show_daynight = false
                width = 2
            yscale = 0.0, 35.0, 5.0
            label = Monthly Out Temp Year Before
            color = 0x42b442
            previous_month = -12
            report_timing = @monthly
                [[[[outTemp]]]]
        
############################################################################################
#
# The list of generators that are to be run:
#
[Generators]
        generator_list = user.translategenerator.ImageGeneratorTranslated
        # generator_list = weewx.imagegenerator.ImageGenerator

#
#    Copyright (c) 2009-2015 Tom Keffer <tkef...@gmail.com>
#
#    See the file LICENSE.txt for your full rights.
#
"""Generate images for up to an effective date.
Needs to be refactored into smaller functions."""

from __future__ import with_statement
import time
import datetime
import syslog
import os.path

import weeplot.genplot
import weeplot.utilities
import weeutil.weeutil
import weewx.reportengine
import weewx.units
from weeutil.config import search_up
from weeutil.weeutil import to_bool, to_int, to_float
from weewx.units import ValueTuple

# =============================================================================
#                    Class ImageGenerator
# =============================================================================

class ImageGenerator(weewx.reportengine.ReportGenerator):
    """Class for managing the image generator."""

    def run(self):
        self.setup()
        self.genImages(self.gen_ts)

    def setup(self):
        try:
            d = self.skin_dict['Labels']['Generic']
        except KeyError:
            d = {}
        self.title_dict = weeutil.weeutil.KeyDict(d)
        self.image_dict = self.skin_dict['ImageGenerator']
        self.formatter  = weewx.units.Formatter.fromSkinDict(self.skin_dict)
        self.converter  = weewx.units.Converter.fromSkinDict(self.skin_dict)
        # ensure that the skin_dir is in the image_dict
        self.image_dict['skin_dir'] = os.path.join(
            self.config_dict['WEEWX_ROOT'],
            self.skin_dict['SKIN_ROOT'],
            self.skin_dict['skin'])
        # ensure that we are in a consistent right location
        os.chdir(self.image_dict['skin_dir'])

    def genImages(self, gen_ts):
        """Generate the images.

        The time scales will be chosen to include the given timestamp, with
        nice beginning and ending times.

        gen_ts: The time around which plots are to be generated. This will
        also be used as the bottom label in the plots. [optional. Default is
        to use the time of the last record in the database.]
        """
        t1 = time.time()
        ngen = 0

        # determine how much logging is desired
        log_success = to_bool(search_up(self.image_dict, 'log_success', True))

        # Loop over each time span class (day, week, month, etc.):
        for timespan in self.image_dict.sections:

            # Now, loop over all plot names in this time span class:
            for plotname in self.image_dict[timespan].sections:

                # Accumulate all options from parent nodes:
                plot_options = weeutil.weeutil.accumulateLeaves(
                    self.image_dict[timespan][plotname])

                plotgen_ts = gen_ts
                if not plotgen_ts:
                    binding = plot_options['data_binding']
                    archive = self.db_binder.get_manager(binding)
                    plotgen_ts = archive.lastGoodStamp()
                    if not plotgen_ts:
                        plotgen_ts = time.time()

 ##  @Andrea __START _last year last month_____________________________________________________________________

                # If previous year or month is set, get the setting and use it to calculate the time span. 
                year = datetime.date.today().year
                month = datetime.date.today().month
                day = datetime.date.today().day

                previous_month = 0
                previous_year = 0
                try:
                    previous_year = int(plot_options.get('previous_year', 0))
                except:
                    raise ValueError("Invalid field value 'previous_year', previous_year can only be a negative integer")

                if previous_year > 0:
                    raise ValueError("Invalid field value 'previous_year' in '%s', previous_year can only be a negative integer" % str(previous_year))

                if previous_year < 0:
##                    plotgen_ts = time.mktime((year + previous_year, 12, 31, 23, 59, 59, 999, 999, 999))
                    plotgen_ts = time.mktime((year + previous_year, month, day, 23, 59, 59, 999, 999, 999))  ## Modified by @Andrea 2018

                if previous_year == 0:
                    try:
                        previous_month = int(plot_options.get('previous_month', 0))
                    except:
                        raise ValueError("Invalid field value 'previous_month', previous_month can only be a negative integer")
                    if previous_month > 0:
                        raise ValueError("Invalid field value 'previous_month' in '%s', previous_month can only be a negative integer" % str(previous_month))

                    if previous_month < 0:
 ##                       plotgen_ts = time.mktime((year, month + previous_month + 1, 1, 0, 0, 0, 0, 0, 0)) - 1
## Modified by @Andrea 2018
                        plotgen_ts = time.mktime((year, month + previous_month, day, 0, 0, 0, 0, 0, 0)) - 1    


##__END______________________________________________________________________

                image_root = os.path.join(self.config_dict['WEEWX_ROOT'],
                                          plot_options['HTML_ROOT'])
                # Get the path that the image is going to be saved to:
                img_file = os.path.join(image_root, '%s.png' % plotname)

                ai = to_int(plot_options.get('aggregate_interval'))
                # Check whether this plot needs to be done at all:
                if skipThisPlot(plotgen_ts, ai, img_file):
                    continue
                    
                # skip image files that are fresh, but only if staleness is defined
                stale = to_int(plot_options.get('stale_age'))
                if stale is not None:
                    t_now = time.time()
                    try:
                        last_mod = os.path.getmtime(img_file)
                        if t_now - last_mod < stale:
                            continue
                    except os.error:
                        pass

                # Create the subdirectory that the image is to be put in.
                # Wrap in a try block in case it already exists.
                try:
                    os.makedirs(os.path.dirname(img_file))
                except OSError:
                    pass

                # Create a new instance of a time plot and start adding to it
                plot = weeplot.genplot.TimePlot(plot_options)

##START plot last Year last Month_______________________________________________________________________ @Andrea

                # If previous_year is less than 0 generate graph for specified calendar year or month
                if previous_year < 0:
                    minstamp = time.mktime((year + previous_year, 1, 1, 0, 0, 0, 0, 0, 0))
                    maxstamp = time.mktime((year + previous_year, 12, 31, 23, 59, 59, 999, 999, 999)) + 1
                elif previous_year == 0 and previous_month < 0:
                    minstamp = time.mktime((year, month + previous_month, 1, 0, 0, 0, 0, 0, 0))
                    maxstamp = time.mktime((year, month + previous_month + 1, 1, 0, 0, 0, 0, 0, 0))
                
##__End_______________________________________________________________________

                # Calculate a suitable min, max time for the requested time.
                (minstamp, maxstamp, timeinc) = weeplot.utilities.scaletime(plotgen_ts - int(plot_options.get('time_length', 86400)), plotgen_ts)
                # Override the x interval if the user has given an explicit interval:
                timeinc_user = to_int(plot_options.get('x_interval'))
                if timeinc_user is not None:
                    timeinc = timeinc_user
                plot.setXScaling((minstamp, maxstamp, timeinc))

                # Set the y-scaling, using any user-supplied hints:
                plot.setYScaling(weeutil.weeutil.convertToFloat(plot_options.get('yscale', ['None', 'None', 'None'])))

                # Get a suitable bottom label:
                bottom_label_format = plot_options.get('bottom_label_format', '%m/%d/%y %H:%M')
                bottom_label = time.strftime(bottom_label_format, time.localtime(plotgen_ts))
                plot.setBottomLabel(bottom_label)

                # Set day/night display
                plot.setLocation(self.stn_info.latitude_f, self.stn_info.longitude_f)
                plot.setDayNight(to_bool(plot_options.get('show_daynight', False)),
                                 weeplot.utilities.tobgr(plot_options.get('daynight_day_color', '0xffffff')),
                                 weeplot.utilities.tobgr(plot_options.get('daynight_night_color', '0xf0f0f0')),
                                 weeplot.utilities.tobgr(plot_options.get('daynight_edge_color', '0xefefef')))

                # Loop over each line to be added to the plot.
                for line_name in self.image_dict[timespan][plotname].sections:

                    # Accumulate options from parent nodes.
                    line_options = weeutil.weeutil.accumulateLeaves(self.image_dict[timespan][plotname][line_name])

                    # See what SQL variable type to use for this line. By
                    # default, use the section name.
                    var_type = line_options.get('data_type', line_name)

                    # Look for aggregation type:
                    aggregate_type = line_options.get('aggregate_type')
                    if aggregate_type in (None, '', 'None', 'none'):
                        # No aggregation specified.
                        aggregate_type = aggregate_interval = None
                    else:
                        try:
                            # Aggregation specified. Get the interval.
                            aggregate_interval = line_options.as_int('aggregate_interval')
                        except KeyError:
                            syslog.syslog(syslog.LOG_ERR, "imagegenerator: aggregate interval required for aggregate type %s" % aggregate_type)
                            syslog.syslog(syslog.LOG_ERR, "imagegenerator: line type %s skipped" % var_type)
                            continue

                    # Now its time to find and hit the database:
                    binding = line_options['data_binding']
                    archive = self.db_binder.get_manager(binding)
                    (start_vec_t, stop_vec_t, data_vec_t) = \
                            archive.getSqlVectors((minstamp, maxstamp), var_type, aggregate_type=aggregate_type,
                                                  aggregate_interval=aggregate_interval)

                    if weewx.debug:
                        assert(len(start_vec_t) == len(stop_vec_t))

                    # Get the type of plot ("bar', 'line', or 'vector')
                    plot_type = line_options.get('plot_type', 'line')

                    if aggregate_type and aggregate_type.lower() in ('avg', 'max', 'min') and plot_type != 'bar':
                        # Put the point in the middle of the aggregate_interval for these aggregation types
                        start_vec_t = ValueTuple([x - aggregate_interval / 2.0 for x in start_vec_t[0]],
                                                 start_vec_t[1], start_vec_t[2])
                        stop_vec_t = ValueTuple([x - aggregate_interval / 2.0 for x in stop_vec_t[0]],
                                                stop_vec_t[1], stop_vec_t[2])

                    # Do any necessary unit conversions:
                    new_start_vec_t = self.converter.convert(start_vec_t)
                    new_stop_vec_t  = self.converter.convert(stop_vec_t)
                    new_data_vec_t = self.converter.convert(data_vec_t)

                    # Add a unit label. NB: all will get overwritten except the
                    # last. Get the label from the configuration dictionary.
                    unit_label = line_options.get('y_label', weewx.units.get_label_string(self.formatter, self.converter, var_type))
                    # Strip off any leading and trailing whitespace so it's
                    # easy to center
                    plot.setUnitLabel(unit_label.strip())

                    # See if a line label has been explicitly requested:
                    label = line_options.get('label')
                    if not label:
                        # No explicit label. Look up a generic one. NB: title_dict is a KeyDict which
                        # will substitute the key if the value is not in the dictionary.
                        label = self.title_dict[var_type]

                    # See if a color has been explicitly requested.
                    color = line_options.get('color')
                    if color is not None: color = weeplot.utilities.tobgr(color)
                    fill_color = line_options.get('fill_color')
                    if fill_color is not None: fill_color = weeplot.utilities.tobgr(fill_color)

                    # Get the line width, if explicitly requested.
                    width = to_int(line_options.get('width'))

                    interval_vec = None
                    gap_fraction = None

                    # Some plot types require special treatments:
                    if plot_type == 'vector':
                        vector_rotate_str = line_options.get('vector_rotate')
                        vector_rotate = -float(vector_rotate_str) if vector_rotate_str is not None else None
                    else:
                        vector_rotate = None

                        if plot_type == 'bar':
                            interval_vec = [x[1] - x[0]for x in zip(new_start_vec_t.value, new_stop_vec_t.value)]
                        elif plot_type == 'line':
                            gap_fraction = to_float(line_options.get('line_gap_fraction'))
                        if gap_fraction is not None:
                            if not 0 < gap_fraction < 1:
                                syslog.syslog(syslog.LOG_ERR, "imagegenerator: Gap fraction %5.3f outside range 0 to 1. Ignored." % gap_fraction)
                                gap_fraction = None

                    # Get the type of line (only 'solid' or 'none' for now)
                    line_type = line_options.get('line_type', 'solid')
                    if line_type.strip().lower() in ['', 'none']:
                        line_type = None

                    marker_type = line_options.get('marker_type')
                    marker_size = to_int(line_options.get('marker_size', 8))
                    
                    # Add the line to the emerging plot:
                    plot.addLine(weeplot.genplot.PlotLine(
                        new_stop_vec_t[0], new_data_vec_t[0],
                        label         = label,
                        color         = color,
                        fill_color    = fill_color,
                        width         = width,
                        plot_type     = plot_type,
                        line_type     = line_type,
                        marker_type   = marker_type,
                        marker_size   = marker_size,
                        bar_width     = interval_vec,
                        vector_rotate = vector_rotate,
                        gap_fraction  = gap_fraction))

                # OK, the plot is ready. Render it onto an image
                image = plot.render()

                try:
                    # Now save the image
                    image.save(img_file)
                    ngen += 1
                except IOError as e:
                    syslog.syslog(syslog.LOG_CRIT, "imagegenerator: Unable to save to file '%s' %s:" % (img_file, e))
        t2 = time.time()

        if log_success:
            syslog.syslog(syslog.LOG_INFO, "imagegenerator: Generated %d images for %s in %.2f seconds" % (ngen, self.skin_dict['REPORT_NAME'], t2 - t1))

def skipThisPlot(time_ts, aggregate_interval, img_file):
    """A plot can be skipped if it was generated recently and has not changed.
    This happens if the time since the plot was generated is less than the
    aggregation interval."""

    # Images without an aggregation interval have to be plotted every time.
    # Also, the image definitely has to be generated if it doesn't exist.
    if aggregate_interval is None or not os.path.exists(img_file):
        return False

    # If its a very old image, then it has to be regenerated
    if time_ts - os.stat(img_file).st_mtime >= aggregate_interval:

        return False

    # Finally, if we're on an aggregation boundary, regenerate.
    time_dt = datetime.datetime.fromtimestamp(time_ts)
    tdiff = time_dt -  time_dt.replace(hour=0, minute=0, second=0, microsecond=0)
    ret = abs(tdiff.seconds % aggregate_interval) > 1

    return ret


Reply via email to