in reply to Can't modify variable received from CGI parameter

As per the documentation:

Note, that just like all the other form elements, the value of a hidden field is "sticky". If you want to replace a hidden field with some other values after the script has been called once you'll have to do it manually:
$query->param('hidden_name','new','values','here');

Add

$cgi->param('species', $species);
at some point before you print the field.